释放内存两次
在C和C ++中,释放NULL指针将导致无法完成任务。
不过,我看到有人说如果你“两次释放内存”会导致内存损坏。
这是真的? 当你释放记忆两次时,引擎盖下发生了什么?
int *p = malloc(sizeof(int)); //value of p is now lets say 0x12345678 *p = 2; free(p); //memory pointer is freed, but still value of p is 0x12345678 //now, if you free again, you get a crash or undefined behavior.
所以,在第一次free
之后,你应该做p = NULL
,所以如果(任何机会),再次调用free(p)
,什么都不会发生。
这就是为什么两次释放内存是未定义的: 为什么在调用两次时自由崩溃
释放内存不会将指针设置为null。 指针仍然指向它曾经拥有的内存,但现在已将所有权转移回堆管理器。
堆管理器可能已经重新分配了陈旧指针所指向的内存。
再次释放它与说free(NULL)
,并将导致未定义的行为。
这是未定义的行为,可能导致堆损坏或其他严重后果。
free()
表示空指针只是检查里面的指针值并返回。 该检查无助于两次释放一个块。
这是通常发生的事情。 堆实现获取地址并尝试通过修改自己的服务数据来“占用”该块的块。 根据堆实现,任何事情都可能发生。 也许它有效并且没有任何反应,也许服务数据已损坏,并且您有堆损坏。
所以不要这样做。 这是未定义的行为。 无论发生什么坏事。
是的,“未定义的行为”几乎总是导致崩溃。 (虽然“未定义的行为”按定义意味着“任何东西”,但各种类型的错误通常以非常可预测的方式运行。在free()的情况下,行为总是会出现段错误或相应的“内存保护错误”特征。)
如果你释放()一个指向除NULL之外的任何东西或者你malloc的东西,那就相同。
char x; char* p=&x; free(p);
//崩溃
为了避免两次免费,我总是使用MACRO获取空闲内存:
#ifdef FREEIF # undef FREEIF #endif #define FREEIF( _p ) \ if( _p ) \ { \ free( _p ); \ _p = NULL; \ }
这个宏设置p = NULL以避免悬空指针。
当您在指针上调用free时,您的指针将不会设置为NULL。 可用空间仅返回池中以便再次分配。 这是一个测试的例子:
#include #include int main(){ int* ptr = (int*)malloc(sizeof(int)); printf("Address before free: %p\n", ptr); free(ptr); printf("Address after free: %p\n", ptr); return 0; }
这个程序为我输出:
Address before free: 0x950a008 Address after free: 0x950a008
你可以看到,free对指针没有任何作用,只是告诉系统内存可以重用。
free()释放ptr指向的内存空间,该内存空间必须由之前调用malloc(),calloc()或realloc()返回。 否则,或者如果之前已经调用了free(ptr),则会发生未定义的行为。 如果ptr为NULL,则不执行任何操作。
所以,你得到了未定义的行为,任何事情都可能发生。
1)编译器不会处理动态内存。 有运行时库来处理这个问题。 例如。 :glibc提供了像malloc和free这样的API,它们在内部进行系统调用(sys_brk)来处理堆区域。
2)释放相同的内存两次指的是这样的条件:假设你有char * cptr;
您可以使用以下命令分配内存:cptr =(char *)malloc(SIZE);
现在,当你不再需要这个内存时,你可以使用它释放它:free(cptr);
现在发生的事情是cptr指向的内存是免费使用的。
假设在程序的稍后时间点再次调用free(cptr),那么这不是一个有效的条件。 这种两次释放相同内存的场景被称为“释放两次内存”问题
不止一次释放内存会产生不良后果。 您可以运行此代码以查看计算机可能发生的情况。
#include /* printf, scanf, NULL */ #include /* malloc, free, rand */ int main () { int i,n; char * buffer; printf ("How long do you want the string? "); scanf ("%d", &i); buffer = (char*) malloc (i+1); if (buffer==NULL) exit (1); for (n=0; n
许多标准库(如CSparse)使用包装函数来处理内存问题。 我复制了这里的function:
/* wrapper for free */ void *cs_free (void *p) { if (p) free (p) ; /* free p if it is not already NULL */ return (NULL) ; /* return NULL to simplify the use of }
此function可以处理内存问题。 请注意,在某些情况下,您必须注意malloc返回NULL的条件