我可以在重新分配指向的内存后重用指针吗?
Can I reuse a pointer after reallocating memory it points to?
我是 C 的新手。我知道当我使用 realloc()
时,指针被停用,因为新的内存块可能位于另一个地址(是否设置为空?)。但是指针只是存储地址的值。那么我可以重用那个指针来存储另一个地址吗?此外,我可以这样做吗:
ptr= realloc(ptr, newsize);
您可以重复使用它,但您应该首先检查重新分配是否成功。
如果重新分配失败,那么在
之后
ptr= realloc(ptr, newsize);
您丢失了对旧内存块的引用,也就是说,您很可能造成了内存泄漏。
您可能想要的是:
void *newptr;
if ( (newptr=realloc(ptr,newsize)) ) ptr = newptr;
else /*handle the error*/;
是的,你可以做到。它本质上没有错。但是,它可能无法从失败的分配中恢复。如果您打算在分配失败时退出程序,那么(通常)没关系。
所以这很好:
ptr = realloc(ptr, newsize);
if(!ptr) exit(EXIT_FAILURE);
这也是:
tmpptr = realloc(ptr, newsize);
if(!tmpptr) puts("Allocation failed. Continuing anyway.");
else ptr = tmpptr;
注意:如果内存泄漏退出是可以争论的。在大多数情况下,这无关紧要,因为操作系统通常会在退出时清理所有内容。所以请注意,在第一个示例中,您将因内存泄漏而退出。
因此,如果内存泄漏对您来说很重要,即使您在失败时退出,您也可以这样做:
tmpptr = realloc(ptr, newsize);
if(!tmpptr) {
free(ptr);
exit(EXIT_FAILURE);
} else {
ptr = tmpptr;
}
但是,请注意,这只会解决 ptr
指针的问题。如果你有一个比简单的学校作业更复杂的程序,那么你很可能已经在进行一些其他分配。跟踪所有可能的事情,但远非微不足道。考虑这个非常简单的例子:
void foo() {
void *ptr1 = malloc(SIZE);
if(!ptr1) exit(EXIT_FAILURE);
bar();
free(ptr1);
}
void bar() {
void *ptr2 = malloc(SIZE);
if(!ptr2) {
// Here we should call free on ptr1 to avoid memory leaks, but how?
exit(EXIT_FAILURE);
}
// Do work
free(ptr2);
}
当然,您可以轻松地重写它:
void foo() {
void *ptr1 = malloc(SIZE);
if(!ptr1) exit(EXIT_FAILURE);
if(!bar()) exit(EXIT_FAILURE);
free(ptr1);
}
int bar() {
void *ptr2 = malloc(SIZE);
if(!ptr2) return 0;
// Do work
free(ptr2);
return 1;
}
在这种情况下,这很容易,但请记住,这个例子非常简单。
除非我有充分的理由关心,否则我不会打扰。它使代码变得混乱,在现代操作系统上完全没有必要。除非我正在为一个重要的环境编写代码,否则我只关心我是否正在编写一个函数,我希望它由调用者决定是否退出。
这里的底线是确保程序在退出时释放所有分配的资源可能是一场彻头彻尾的噩梦。除非你有它的需要并且愿意花很多时间把它做好,否则别费心了。
实际上,处理这个问题需要您在设计的几乎所有方面都考虑到这一点。这很少是一个好的权衡。
相关问题:dangers of _exit() - memory leak?
我是 C 的新手。我知道当我使用 realloc()
时,指针被停用,因为新的内存块可能位于另一个地址(是否设置为空?)。但是指针只是存储地址的值。那么我可以重用那个指针来存储另一个地址吗?此外,我可以这样做吗:
ptr= realloc(ptr, newsize);
您可以重复使用它,但您应该首先检查重新分配是否成功。
如果重新分配失败,那么在
之后ptr= realloc(ptr, newsize);
您丢失了对旧内存块的引用,也就是说,您很可能造成了内存泄漏。
您可能想要的是:
void *newptr;
if ( (newptr=realloc(ptr,newsize)) ) ptr = newptr;
else /*handle the error*/;
是的,你可以做到。它本质上没有错。但是,它可能无法从失败的分配中恢复。如果您打算在分配失败时退出程序,那么(通常)没关系。
所以这很好:
ptr = realloc(ptr, newsize);
if(!ptr) exit(EXIT_FAILURE);
这也是:
tmpptr = realloc(ptr, newsize);
if(!tmpptr) puts("Allocation failed. Continuing anyway.");
else ptr = tmpptr;
注意:如果内存泄漏退出是可以争论的。在大多数情况下,这无关紧要,因为操作系统通常会在退出时清理所有内容。所以请注意,在第一个示例中,您将因内存泄漏而退出。
因此,如果内存泄漏对您来说很重要,即使您在失败时退出,您也可以这样做:
tmpptr = realloc(ptr, newsize);
if(!tmpptr) {
free(ptr);
exit(EXIT_FAILURE);
} else {
ptr = tmpptr;
}
但是,请注意,这只会解决 ptr
指针的问题。如果你有一个比简单的学校作业更复杂的程序,那么你很可能已经在进行一些其他分配。跟踪所有可能的事情,但远非微不足道。考虑这个非常简单的例子:
void foo() {
void *ptr1 = malloc(SIZE);
if(!ptr1) exit(EXIT_FAILURE);
bar();
free(ptr1);
}
void bar() {
void *ptr2 = malloc(SIZE);
if(!ptr2) {
// Here we should call free on ptr1 to avoid memory leaks, but how?
exit(EXIT_FAILURE);
}
// Do work
free(ptr2);
}
当然,您可以轻松地重写它:
void foo() {
void *ptr1 = malloc(SIZE);
if(!ptr1) exit(EXIT_FAILURE);
if(!bar()) exit(EXIT_FAILURE);
free(ptr1);
}
int bar() {
void *ptr2 = malloc(SIZE);
if(!ptr2) return 0;
// Do work
free(ptr2);
return 1;
}
在这种情况下,这很容易,但请记住,这个例子非常简单。
除非我有充分的理由关心,否则我不会打扰。它使代码变得混乱,在现代操作系统上完全没有必要。除非我正在为一个重要的环境编写代码,否则我只关心我是否正在编写一个函数,我希望它由调用者决定是否退出。
这里的底线是确保程序在退出时释放所有分配的资源可能是一场彻头彻尾的噩梦。除非你有它的需要并且愿意花很多时间把它做好,否则别费心了。
实际上,处理这个问题需要您在设计的几乎所有方面都考虑到这一点。这很少是一个好的权衡。
相关问题:dangers of _exit() - memory leak?