C 分配内存并释放它们。我们应该将它们设置为NULL吗?
你好, 我想知道我的想法是否正确。当我使用malloc分配内存时。malloc将返回指向内存中某个大小的指针 因此,在分配内存之前,所有指针的值都将为NULL 使用此代码段:C 分配内存并释放它们。我们应该将它们设置为NULL吗?,c,malloc,free,C,Malloc,Free,你好, 我想知道我的想法是否正确。当我使用malloc分配内存时。malloc将返回指向内存中某个大小的指针 因此,在分配内存之前,所有指针的值都将为NULL 使用此代码段: gcc (GCC) 4.7.0 c89 在分配内存之前,我已在db_行的gdb调试器中完成了此操作: struct address *db_row = NULL; db_row = malloc(sizeof(struct address)); db_row->name = malloc(sizeof(char)
gcc (GCC) 4.7.0
c89
在分配内存之前,我已在db_行的gdb调试器中完成了此操作:
struct address *db_row = NULL;
db_row = malloc(sizeof(struct address));
db_row->name = malloc(sizeof(char) * 10);
db_row->email = malloc(sizeof(char) *10);
free(db_row->name);
free(db_row->email);
free(db_row);
这是正确的,因为没有分配内存地址。
分配内存后,当我执行相同操作时,会得到以下结果:
(gdb) p db_row
$20 = (struct address *) 0x0
(gdb) p *db_row
Cannot access memory at address 0x0
然而,在释放内存后,我仍然会得到相同的内存地址,在分配任何内存之前,它是否应该像第一种情况一样为空
释放内存后:
(gdb) p db_row
$25 = (struct address *) 0x602310
(gdb) p *db_row
$26 = {id = 0, set = 0, name = 0x0, email = 0x0}
正如您所看到的,它仍然指向相同的内存位置,这是正确的吗
最后,我在结尾添加了这个,以查看是否可以进行双重免费:
(gdb) p db_row
$28 = (struct address *) 0x602310
(gdb) p *db_row
$27 = {id = 6300480, set = 0, name = 0x602330 "", email = 0x602350 " #`"}
我在第二次调用free时得到一个堆栈转储。但是,作为一项安全措施,你是否应该经常检查以确保你没有试图做双重自由
释放指针后是否值得将其设置为NULL
if(db_row != NULL) {
free(db_row);
}
if(db_row != NULL) {
free(db_row);
}
非常感谢您的建议
释放内存后,我仍然会得到相同的内存地址,在分配任何内存之前,它是否应该像第一种情况一样为空?
因为free()
只释放分配给您的内存。它不会将指针设置为NULL
但是作为一项安全措施,您是否应该始终检查以确保您没有试图释放空指针?
如果传递到free()
的指针为空指针,则不会发生任何操作(C99第7.20.3.2节)
释放指针后,是否值得将指针设置为NULL
?
这样做是绝对没有好处的,更多的时候,它最终会隐藏你的问题,以某种或其他形式抬高他们丑陋的头
这是一种防御性的、可疑的编程风格,以避免指针悬空或双重自由问题,即试图保护自己免受free()
在相同的指针上被调用。实际上,当不同的指针指向同一内存,并且这些不同的指针被传递到free()
时,往往会出现双自由问题
在第二个也是更常见的bug场景中,使指针NULL
无效的做法没有任何作用。所有这些情况都只能通过编写程序来避免,方法是进行一些好的思考和定期的代码检查
但作为一种安全措施,您是否应该始终检查以确保您没有试图释放空指针
使用NULL
指针调用free()。调用free()
不会NULL
指针,您可以显式执行此操作NULL
调用free()
后调用指针将阻止对同一指针变量执行双自由:
db_row = NULL;
如果另一个指针变量指向同一地址,并被传递到free()
,则仍然会出现双自由。
指针不为空并不保证它指向有效地址。程序员有责任确保不会出现双重free()
sNULL
调用free()
后调用指针变量有帮助,但不能提供保证,因为多个指针变量可以指向同一地址
但是,作为一项安全措施,你是否应该经常检查以确保你没有试图做双重自由
无法查询指针变量以确定其所在地址的内存是否已被free()
d。指针变量保存地址,仅此而已。最好在释放指针后将其设置为null
,除非您位于变量范围的末尾;是的,free
不这样做是正常的
如果指针为null
,则在其上调用free
是安全的,并且对它的任何访问都将生成一个内核转储,这比使用未设置为null
的已释放指针尝试清除此处的内存损坏或双重free
更容易调试,我将引用malloc的手册页:
free()函数释放ptr指向的内存空间,该内存空间必须由先前对malloc()、calloc()或realloc()的调用返回。否则,或者如果之前已经调用了free(ptr),则会发生未定义的行为。如果ptr为NULL,则不执行任何操作。
因此,总结一下:
Free接受内存分配函数返回的指针(NULL或valid)
如果为NULL,则不会发生任何事情
如果它是有效指针,则会释放内存
您会注意到,这里没有关于更改ptr
指向的地址的内容。那由你来做。因此,这样做非常安全:
/* Assuming 'db_row' is referring to a valid address
at this stage the following code will not result
in a double free.*/
free(db_row);
db_row = NULL;
free(db_row);
现在你可以整天用指针p调用free()
,你就没事了。如果您担心在最近版本的Linux libc(5.4.23之后)和GNU libc(2.x)上进行双重free()
调用时出现错误,那么有一种安全机制,称为MALLOC\u CHECK
您将看到如下消息,而不是堆栈崩溃:
***glibc检测到***./a.out:free():无效指针:0x0804b008***
您可以通过以下方式使用它:
导出MALLOC\u CHECK\u=0
关闭MALLOC CHECK并(可能)让程序崩溃
导出MALLOC\u CHECK\u=1
您将收到上述警告消息
export MALLOC\u CHECK\u2
将调用abort(1)并返回代码跟踪
导出MALLOC\u CHECK\u3
只是选项1|
int *p = malloc(sizeof(int));
*p = 5;
printf("p=%d\n",*p);
free(p);
p = NULL;