尽管如此,我看到有人说如果“free一个已经被释放了的内存”,那么可能会导致内存损坏。
这是真的吗?当你两次释放内存时,底层发生了什么?
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)
,则什么也不会发生。
释放内存两次未定义的原因在于:为什么重复调用free会导致崩溃
free
,那么这是一个(有点)糟糕的实现。 - N 1.1free
语句之前检查它是否为空。 - Janusz Lenar释放内存并不会将指针设置为 null。 指针仍然指向它曾经拥有的内存,但现在所有权已被转移回堆管理器。
堆管理器可能已经重新分配了您的陈旧指针所指向的内存。
再次释放它并不意味着说 free(NULL)
,这将导致未定义行为。
free()
仅检查内部指针值并返回。该检查无法防止两次释放同一块。为了避免重复释放内存,我总是使用宏来释放内存:
#ifdef FREEIF
# undef FREEIF
#endif
#define FREEIF( _p ) \
if( _p ) \
{ \
free( _p ); \
_p = 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函数并没有对指针所指向的内存做任何修改,只是告诉系统这块内存可以被重新使用。
char x; char* p=&x; free(p);
// 崩溃。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 <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的条件。