在C和C ++中,释放空指针将导致无法完成任务。
不过,我看到有人说如果“两次释放内存”会导致内存损坏。
这是真的吗?当你两次释放记忆时,幕后发生了什么?
答案 0 :(得分:23)
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)
,就不会发生任何事情。
这就是为什么两次释放内存是未定义的:Why free crashes when called twice
答案 1 :(得分:19)
释放内存不会将指针设置为null。指针仍然指向它曾经拥有的内存,但现在已将所有权转移回堆管理器。
堆管理器可能已经重新分配了陈旧指针所指向的内存。
再次释放它与说free(NULL)
不同,并且会导致未定义的行为。
答案 2 :(得分:9)
这是未定义的行为,可能导致堆损坏或其他严重后果。
free()
对于空指针只是检查内部的指针值并返回。该检查无助于两次释放一个块。
这是通常会发生的事情。堆实现获取地址并尝试通过修改自己的服务数据来“占用”该块的块。根据堆实现,任何事情都可能发生。也许它工作正常,没有任何反应,也许服务数据已损坏,你的堆已经腐败。
所以不要这样做。这是未定义的行为。无论发生什么坏事。
答案 3 :(得分:4)
是的,“未定义的行为”几乎总会导致崩溃。 (根据定义,“未定义的行为”意味着“任何东西”,各种类型的错误通常以非常可预测的方式运行。在free()的情况下,行为总是会出现段故障或相应的“内存保护错误”特征。)< / p>
如果你释放()一个指向除NULL之外的任何东西或者你malloc'd的东西,那就相同。
char x; char* p=&x; free(p);
//崩溃。
答案 4 :(得分:4)
为了避免免费两次,我总是使用MACRO获取空闲内存:
#ifdef FREEIF
# undef FREEIF
#endif
#define FREEIF( _p ) \
if( _p ) \
{ \
free( _p ); \
_p = NULL; \
}
这个宏设置p = NULL以避免悬空指针。
答案 5 :(得分:3)
当你在指针上调用free时,你的指针不会被设置为NULL。可用空间仅返回池中以便再次分配。这是一个测试的例子:
#include <stdio.h>
#include <stdlib.h>
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对指针没有任何作用,只是告诉系统内存可以重用。
答案 6 :(得分:2)
free()释放指向的内存空间 通过ptr,一定是 之前的电话回复 malloc(),calloc()或realloc()。 否则,或者如果已经免费(ptr) 以前被称为未定义 行为发生。如果 ptr为NULL,不执行任何操作。
因此,您会得到未定义的行为,并且可能发生任何事情。
答案 7 :(得分:1)
1)编译器不会处理动态内存。有运行时库来处理这个问题。例如。 :glibc提供了malloc和free之类的API,它们在内部进行系统调用(sys_brk)来处理堆区域。
2)两次释放相同的内存指的是这样的条件: 假设你有char * cptr;
您使用以下方式分配内存: cptr =(char *)malloc(SIZE);
现在,当您不再需要此内存时,可以使用以下内容释放它: 自由(CPTR);
现在发生的事情是cptr指向的内存可以免费使用。
假设在程序的稍后时间你再次调用free(cptr),那么这不是一个有效的条件。这种情况下,你释放两次相同的内存被称为“释放两次内存”问题。
答案 8 :(得分:0)
多次释放内存可能会产生不良后果。您可以运行此代码来查看计算机可能发生的情况。
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* 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<i; n++)
buffer[n]=rand()%26+'a';
buffer[i]='\0';
printf ("Random string: %s\n",buffer);
free (buffer);
free (buffer);
return 0;
}
许多标准库(如CSparse)使用处理内存问题的包装函数。 我在这里复制了这个功能:
/* 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
}
此功能可以处理内存问题。请注意,在某些情况下,您必须注意malloc返回NULL的条件