c-分配内存并释放它们.我们应该将它们设置为NULL吗


gcc (GCC) 4.7.0
c89

你好,

我想知道我的想法是否正确。当我使用malloc分配内存时。malloc将返回一个指向内存中某个大小的指针。

因此,在分配内存之前,所有指针的值都将为NULL。

使用以下代码片段:

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);

在分配内存之前,我已经在db_row的gdb调试器中完成了这一操作:

(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}

然而,在我释放内存后,我仍然得到相同的内存地址,在分配任何内存之前,它是否应该像第一种情况一样为NULL?

释放内存后:

(gdb) p db_row
$28 = (struct address *) 0x602310
(gdb) p *db_row
$27 = {id = 6300480, set = 0, name = 0x602330 "", email = 0x602350 " #`"}

正如你所看到的,它仍然指向同一个内存位置,这是正确的吗?

最后,我在最后添加了这个,看看我是否可以做两次免费:

if(db_row != NULL) {
free(db_row);
}
if(db_row != NULL) {
free(db_row);
}

我在第二次调用free时得到堆栈转储。但作为一项安全措施,你是否应该经常检查,以确保你没有试图做双重免费?

释放指针后将其设置为NULL值得吗?

db_row = NULL;

非常感谢您的任何建议,

但是作为一种安全措施,您是否应该始终检查以确保您没有试图释放NULL指针?

使用NULL指针调用free()是安全的,不会发生任何事情。调用free()不会将NULL作为指针,您可以显式执行此操作。NULL在调用free()后调用指针将阻止同一指针变量上的双空闲

/* 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);

如果另一个指针变量指向同一地址并被传递给free(),则仍会出现双空闲

仅仅因为指针不是-NULL并不能保证它指向一个有效的地址。程序员有责任确保不会出现双free()。在调用free()之后调用NULL指针变量有帮助,但不能提供保证,因为多个指针变量可以指向同一地址。


但作为一项安全措施,你是否应该始终检查以确保你没有试图进行双重免费?

无法查询指针变量来确定其所在地址的内存是否已为free()d。指针变量只包含地址。

最好在释放指针后将其设置为null,除非您位于变量范围的末尾;是的,CCD_ 14不这样做是正常的。

如果指针是null,则在其上调用free是安全的,并且对其的任何访问都将生成核心转储,这比使用未设置为null的释放指针时可能发生的内存损坏或双free更容易调试。

释放内存后,我仍然会得到相同的内存地址,在分配内存之前,它是否应该像第一种情况一样为NULL

因为free()只释放分配给您的内存。它不将指针设置为NULL

但是作为一种安全措施,您是否应该始终检查以确保您没有试图释放NULL指针

如果传递给free()的指针为空指针,则不会发生任何操作(C99第7.20.3.2节)。

释放指针后,是否值得设置指向NULL的指针

这样做绝对没有任何好处,更常见的情况是,它最终会隐藏你的问题,这会以某种或其他形式引起他们丑陋的头脑。

这是一种防御性和可疑的编程风格,以避免悬挂指针或双自由问题,其中您试图保护自己免受free()相同指针上被调用的影响。实际上,当不同的指针指向同一内存,并且这些不同的指针被传递到free()时,通常会出现双自由问题。

使指针NULL的做法在第二个也是更常见的bug场景中没有任何作用。所有这些情况只能通过编写程序来避免,方法是投入一些好的思想和定期的代码审查。

为了在这里说清楚,我将引用malloc:的手册页

The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.

所以,概括一下:

  1. Free获取内存分配函数返回的指针(NULL或有效)
  2. 如果为NULL,则不会发生任何事情
  3. 如果它是一个有效的指针,它将释放内存

您会注意到,在这里,它对更改ptr所指向的地址没有任何内容。这是您的责任。因此,这样做非常安全:

int *p = malloc(sizeof(int));
*p = 5;
printf("p=%dn",*p);
free(p);
p = NULL;

现在,你可以整天在指针p上调用free(),你就可以了。如果你担心双free()调用会出错,那么在最新版本的Linux libc(5.4.23之后)和GNU libc(2.x)上,有一种安全的机制,叫做MALLOC_CHECK_

您将看到以下消息,而不是出现堆栈崩溃:*** glibc detected *** ./a.out: free(): invalid pointer: 0x0804b008 ***

您可以通过以下方式使用它:

  1. export MALLOC_CHECK_=0关闭malloc检查并(可能)让程序崩溃
  2. export MALLOC_CHECK_=1您将收到上述警告信息
  3. export MALLOC_CHECK_=2将调用abort(1)并返回代码
  4. export MALLOC_CHECK_=3只是选项1|2

相关内容

  • 没有找到相关文章

最新更新