无法基于用户动态分配内存';s弦;realloc():下一个大小无效

无法基于用户动态分配内存';s弦;realloc():下一个大小无效,c,struct,dynamic-memory-allocation,realloc,callstack,C,Struct,Dynamic Memory Allocation,Realloc,Callstack,我正在尝试最小化以下程序的内存分配。我尝试动态分配内存的整个想法是 为用户的字符串输入动态分配30字节的内存 如果用户的输入大于分配的内存,则调用realloc()函数使字符串适合101字节 如果用户的输入大于100字节,则调用exit()并终止程序 当我实现realloc()函数来检查用户输入是否适合动态分配的字符数组(与calloc连成一行)时,我的程序失败,输出如下: realloc(): invalid next size Aborted (core dumped) 我不知道如何解决它

我正在尝试最小化以下程序的内存分配。我尝试动态分配内存的整个想法是

  • 为用户的字符串输入动态分配30字节的内存
  • 如果用户的输入大于分配的内存,则调用realloc()函数使字符串适合101字节
  • 如果用户的输入大于100字节,则调用exit()并终止程序
  • 当我实现realloc()函数来检查用户输入是否适合动态分配的字符数组(与calloc连成一行)时,我的程序失败,输出如下:

    realloc(): invalid next size
    Aborted (core dumped)
    
    我不知道如何解决它

    代码:

    #include//get()已从此库中删除
    #包括//用于calloc()
    #包括//用于strlen()
    #包括//用于睡眠(2)
    int len=0;
    结构项
    {
    //我不能确保指针指向任何东西,因为结构只是一个模板。
    //我不能在这里做手术!!!!!!!
    字符*项目名称;
    整数数量;
    浮动价格;
    浮动金额;
    };
    int readItem(结构项*pProduct)
    {
    printf(“嘿,产品名称是什么:”);
    获取(PPProduct->itemName);
    //检查用户输入是否符合分配的指针大小
    len=strlen(产品->项目名称);
    printf(“%d\n\n”,len);
    如果(长度>30)
    {
    //这里出错
    ppproduct->itemName=(char*)realloc(ppproduct->itemName,101);
    printf(“\n您的输入太大,请重新输入\n”);
    获取(PPProduct->itemName);
    如果(PPProduct->itemName==NULL)
    {
    puts(“内存不可用”);
    出口(1);
    }
    len=strlen(产品->项目名称);
    printf(“%d\n\n”,len);
    如果(len>100)
    {
    puts(“内存不可用”);
    出口(1);
    }
    }
    printf(“\n输入产品数量:”);
    scanf(“%d”,&P产品->数量);
    printf(“\n输入产品价格:”);
    scanf(“%f”,&p产品->价格);
    //计算金额
    p产品->金额=(浮动)p产品->数量*p产品->价格;
    返回0;
    }
    无效打印项(结构项*pProduct)
    {
    puts(“\n\n数据库:”);
    睡眠(1);
    printf(“-------------------------\n”);
    printf(“名称:\%s\“\n”,(*pProduct.itemName);
    printf(“价格:%.2f\n”,p产品->价格);
    printf(“数量:%d\n”,p产品->数量);
    printf(“金额:%.2f\n”,p产品->金额);
    printf(“-------------------------\n”);
    }
    int main()
    {
    //将变量product和PIPPRODUCT分配给标记名项,
    结构项产品,*pProduct=NULL;
    //存储指向指针pProduct的地址
    //创建指向指针的结构
    p产品=&product;
    //(char*)正在将char强制转换为指针类型
    ppproduct->itemName=(char*)calloc(30,sizeof(char));
    readItem(pProduct);
    打印项目(pProduct);
    免费(PPProduct->itemName);
    p产品->项目名称=NULL;
    pProduct=NULL;
    返回0;
    }
    
    我确切地知道是REALLOC引起了麻烦。更准确地说,如果我输入34个字符,realloc似乎可以工作,但是如果将其加倍到68,它会抛出错误,尽管realloc中提到了大小

    我对调用堆栈一无所知,但它可能对某些人有用:

    
        libc.so.6!__GI_raise(int sig) (/build/glibc-YYA7BZ/glibc-2.31/sysdeps/unix/sysv/linux/raise.c:50)
         
        libc.so.6!__GI_abort() (/build/glibc-YYA7BZ/glibc-2.31/stdlib/abort.c:79)
         
        libc.so.6!__libc_message(enum __libc_message_action action, const char * fmt) (/build/glibc-YYA7BZ/glibc-2.31/sysdeps/posix/libc_fatal.c:155)
         
        libc.so.6!malloc_printerr(const char * str) (/build/glibc-YYA7BZ/glibc-2.31/malloc/malloc.c:5347)
    
        libc.so.6!_int_realloc(mstate av, mchunkptr oldp, size_t oldsize, size_t nb) (/build/glibc-YYA7BZ/glibc-2.31/malloc/malloc.c:4564)
         
        libc.so.6!__GI___libc_realloc(size_t bytes, void * oldmem) (/build/glibc-YYA7BZ/glibc-2.31/malloc/malloc.c:3226)
         
        libc.so.6!realloc_hook_ini(void * ptr, size_t sz, const void * caller) (/build/glibc-YYA7BZ/glibc-2.31/malloc/hooks.c:41)
         
        readItem(struct item * pProduct) (/home/max/My stuff/programming/Udemy/section 14, reading and wrinting files/test.c:22)
         
        main() (/home/max/My stuff/programming/Udemy/section 14, reading and wrinting files/test.c:72)
    
    
    libc.so.6__GI_-raise(int-sig)(/build/glibc-YYA7BZ/glibc-2.31/sysdeps/unix/sysv/linux/raise.c:50)
    libc.so.6__GI_abort()(/build/glibc-YYA7BZ/glibc-2.31/stdlib/abort.c:79)
    libc.so.6__libc_message(枚举libc_message_action action,const char*fmt)(/build/glibc-YYA7BZ/glibc-2.31/sysdeps/posix/libc_fatal.c:155)
    libc.so.6!malloc_printerr(const char*str)(/build/glibc-YYA7BZ/glibc-2.31/malloc/malloc.c:5347)
    libc.so.6_int_realloc(mstate av,mchunkptr oldp,size_t oldsize,size_t nb)(/build/glibc-YYA7BZ/glibc-2.31/malloc/malloc.c:4564)
    libc.so.6__GI__________libc_realloc(字节大小,void*oldmem)(/build/glibc-YYA7BZ/glibc-2.31/malloc/malloc.c:3226)
    libc.so.6!realloc_hook_ini(void*ptr,size_t sz,const void*caller)(/build/glibc-YYA7BZ/glibc-2.31/malloc/hooks.c:41)
    readItem(struct item*pProduct)(/home/max/My stuff/programming/Udemy/section 14,读取和写入文件/test.c:22)
    main()(/home/max/My stuff/programming/Udemy/section 14,读取和写入文件/test.c:72)
    
    建议

    分配一个长缓冲区,比可能需要的时间长得多。然后通过调用
    fgets()

    -或-

    使用
    getline()
    函数读取数据

    char *buffer = NULL;
    size_t byteCount;
    getline( &line, &byteCount, stdin );
    

    注意:为了简化说明,我在上面留下了错误检查。

    当您写入超出分配内存的范围时,通常会出现此错误。如果您无法通过常规调试技术(如或在调试器中逐条检查代码语句)找到问题,您可以使用诸如之类的工具来帮助您。一个明显的问题是:注释
    //gets()已从此库中删除
    ,但您仍然使用
    gets
    ?为什么?这是一个函数,不应该使用。这可能是崩溃的原因,因为在您检查之前,它会写入超出分配内存的范围。在将其读入
    pProduct->itemName
    后检查长度是错误的。如果输入太长,则在测试之前,它已经溢出了缓冲区。此外,30字节的分配只能容纳长度不超过29个字符的字符串,因为终止空字符需要一个字节,但不计入长度。
    if(len>100)
    是一个问题。除非先前的缓冲区溢出(这是未定义的行为),否则它不可能为真。使用
    fgets()
    char buffer[1024];
    fgets( buffer, sizof( buffer ), stdin );
    
    char *buffer = NULL;
    size_t byteCount;
    getline( &line, &byteCount, stdin );