使用free()函数

时间:2013-10-10 06:31:29

标签: c memory-management malloc free

我对C中的free()函数的行为提出了一般性问题。

我是否正确地假设通过调用free()它只是释放指针指向的内存,但保留指针完整?

换句话说,如果我想重用指针,那么指针不需要重新初始化,只需重新分配内存?

例如,这段代码是否合法?

原始版本

void foo()
{
    data_t *x;
    int y = 0;

    while(x->data != some_value)
    {
        x = some_function(y);
        y = some_other_function(x);
        free(x);
    }
}

修订版

void foo()
{
    data_t *x;
    int y = 0;

    x = some_function(y);

    while(x->data != some_value)
    {
        y = some_other_function(x);
        free(x);
        x = some_function(y);
    }
}

忽略实际代码(以及data_t的内部结构)并假设some_function()正确malloc() s x;我只是想知道这是一种管理内存的正确方法,还是我需要在每次免费后重新初始化data_t *x

编辑:我编辑了代码,因为我意识到它没有正确说明我的问题。

5 个答案:

答案 0 :(得分:2)

释放x然后转到下一个while检查会导致未定义的行为

因为在下一次while检查中,您创建了while(x->data != some_value)并且x已经被释放

在进行下一次x检查之前,您必须将while分配给下一个值

BTW:即使在开始时(在第一次检查中),您也有未定义的行为,因为x未在while循环之前启动到内存区域。< / p>


基于问题编辑

新案例中的free(x)无效。

当你释放x时,x指针保留指向x的旧内存地址但是内存不再分配它是免费的。

在空闲后将新分配的内存分配给x时,x将指向新的内存区域

答案 1 :(得分:1)

是的,修改后的代码版本是管理内存的正确方法。无需再次重新初始化x。只需要确保释放x后,永远不要使用它。但是,您可以再次为其重新分配一些内存并使用它。

答案 2 :(得分:1)

  

它只是释放指针指向的内存,但是指针保持不变?

这是对的。如果free()是普通的C函数,则它无法影响传递给它的指针值。由于C通过值传递参数,free()接收传递给它的指针的副本,并且它不能改变原始的x指针。 (它可以改变x点

  

换句话说,如果我想重用指针,那么指针不需要重新初始化,只需重新分配内存?

free(x);
x = some_function(y);

这正是你在这里所做的,你将x分配给其他东西,所以这就是人们通常会做的事情。 指针包含一个地址,并为其分配另一个地址。

这与以下概念相同:

 int x 
 x = function_that_returns_int();
 x = function_that_returns_int();

您只需为i分配新值,在为其分配新值之前,无需对i执行任何其他操作。

答案 3 :(得分:1)

根据ISO C标准中的抽象语言定义,在对来自分配器的有效非空指针调用free之后,该指针的值变为 indeterminate 。对该值的任何使用都是未定义的行为。不确定的值不能再次生效。

在C的实际实现中,程序中存在的不确定指针值可以在没有检测的情况下传递和评估,当内存被回收到新分配的对象时,它们与有效指针无法区分,从而导致各种问题。

这并不违反规范,因为任何行为都属于未定义行为的范畴。

如果编写的程序行为可靠,但依赖于通过内存分配复活的悬挂指针,则该程序根据ISO C没有明确定义,并且根据您的不太可能很好地定义编译器或操作系统文档,或者。

已编译的程序今天可以正常工作,但明天,libc.so中的malloc代码会更新,因此内存的回收方式会有所不同,而且会中断。

测试程序产生预期的行为很重要,但这不是完整的故事。行为还必须依赖于语言规范,系统和工具文档的一些保证,或者失败,某些理性的推理让你对程序的正确运行负责。

后者的一个例子是,有时我们可以在语言级别滥用C编译器以获得一些所需的机器代码。虽然这不是由ISO C定义的,甚至可能不是由编译器开发人员定义的,但是一旦你拥有了机器代码,那么在某种意义上说你如何得到它并不重要;它可以独立检查,看它做你想要的。您可以对此负责,并设置回归保护措施,以监控该代码以进行不必要的更改(当编译器以不同方式运行或升级或其他任何操作时)。

对于mallocfree的行为,你不能轻易承担这种责任,这是一个运行时黑盒子,它的行为可以在程序部署后很长时间内改变。< / p>

答案 4 :(得分:0)

while条件检查无效,因为x没有指向任何已分配的内存。因此它会导致一些垃圾值。但是,如果代码进入while循环,则x被分配一些内存然后被释放。所以x现在变成了悬空指针。在下一次检查时它也会包含一些垃圾值。在某些情况下,如果指针试图访问属于其他进程的某些数据,甚至会导致分段错误。