我使用realloc()
来动态调整某些数组的大小。因为我写了很多像这样的代码:
void *tmp;
if( (tmp = realloc(myobject, sizeof(object) * newsize) != NULL)
myobject = tmp
我以为我会通过做这样的事情来缩短我的代码(愚蠢的想法):
void GetSpace(void *ptr, size_t size_of_object, int newsize){
void *tmp = NULL;
if ((tmp = realloc(ptr, size_of_object * newsize) == NULL)
//print error msg and exit
else
ptr = tmp;
}
int main(){
//This is an example
double *mydata1 = (double *)malloc (sizeof double * 5);
//later request more space for mydata1
GetSpace( mydata1, sizeof(double), 50);
}
这很愚蠢,因为它不会保存那么多行或使代码更具可读性但我想知道为什么它不能按照我期望的方式工作。当我将GetSpace()
用于单个对象时,它只能正常工作。如果我在没有初始化我调用函数的任何对象的情况下运行代码,它运行正常但是当我为一个对象调用GetSpace()
时,然后将数据放入其中,然后调用GetSpace()
代替另一个对象,我得到一个像这样的消息的堆栈跟踪
*** glibc detected *** ./a.out: realloc(): invalid old size: 0x00007fff05d96790 ***
0x00007fff05d96790
是调整大小之前第二个数组/对象的地址。为什么会这样?
答案 0 :(得分:3)
在GetSpace
函数中,您将分配一个具有更大大小的新内存块,并将该地址分配给本地变量ptr
。但是当函数退出时,这个新地址就会丢失。您的主程序仍然具有旧值ptr
,现在指向无效(释放)内存。
您需要将新地址返回给调用者。试试这个。请注意,参数ptr
现在通过引用传递,因此更新了调用者的变量。
void GetSpace(void **ptr, size_t size_of_object, int newsize){
void *tmp = NULL;
if ((tmp = realloc(*ptr, size_of_object * newsize) == NULL)
//print error msg and exit
else
*ptr = tmp;
}
编辑:正如评论中所指出的那样,这仍然不太理想,因为你必须做凌乱的转换才能将指针的地址作为void**
传递。一个改进是分别返回新指针,如下所示:
void *GetSpace(void *ptr, size_t size_of_object, int newsize){
void *tmp = NULL;
if ((tmp = realloc(ptr, size_of_object * newsize) == NULL)
//print error msg and exit
else
return tmp;
}
int main(){
...
//later request more space for mydata1
mydata1 = GetSpace( mydata1, sizeof(double), 50);
}