无法基于用户动态分配内存';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) 我不知道如何解决它
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 );