这是释放动态分配内存的好习惯吗?

问题描述 投票:0回答:3

我写了下面的代码示例:

#include <stdio.h>
#include <stdlib.h>

char *test(void);

int main()
{
    char *base_ptr = NULL;

    base_ptr = test();

    for (char i = 0; i < 5; i++)
    {
        printf("base_ptr[%hhi] = %hhi\n", i, base_ptr[i]);
    }

    free(base_ptr);
    
    return 0;
}

char *test(void)
{
    char *local_ptr = NULL;


    local_ptr = (char *)malloc(5*sizeof(char));

    for (char i = 0; i < 5; i++)
    {
        scanf(" %hhi", &local_ptr[i]);
    }

    return local_ptr;
}

所以,我知道一旦被“malloc()”或“calloc()”分配,我必须使用“

free()
”函数释放分配的内存。

在我展示的代码示例中,我在函数“test”中进行分配,它返回一个指针。返回的指针携带分配数组的基地址。在函数“

test()
”中没有使用函数“
free()
”,因为到达返回运算符,程序离开了函数,这导致从函数本身释放内存,所以从它的所有局部变量,包括保存基地址的指针。

但是在函数“

main()
”中,我将该地址保存在指针“
base_ptr
”中。我正在打印我在已经终止的函数“
test()
”中分配的所有值,然后我使用函数“
free()
”释放基地址。

我对此有几个问题。

这种释放分配内存的方式是否会产生内存泄漏的风险,这是一个好的做法吗?

通过

function end
return
释放动态分配的内存是否与“
free()
”功能相同?

如果函数“

test()
”占用(和初始化)的内存由于执行结束而被释放,那么以代码示例中的方式访问它的地址是否危险?

c memory dynamic-memory-allocation
3个回答
1
投票

但是在函数“main()”中,我将该地址保存在 指针“base_ptr”。我正在打印我分配的所有值 已经终止的函数“test()”,然后我将释放 base 地址,使用函数“free()”。

从函数返回不会释放通过

malloc
系列函数分配的内存。这些内存块的生命周期与程序相同,除非你自己
free
它们。在您的函数中,您不返回本地指针,仅返回对已分配内存的引用,并且此引用存储在该本地指针中。

自动存储持续时间对象的生命周期与封闭范围相同,当您离开该范围时它们将停止存在

例子:

int *foo(void)
{
    int a[10];
    return a;  //returning pointer to the object which lifetime will end when 
               //function returns. If you use this returned value 
               //it will invoke undefined behaviour
}

正在通过函数结束释放动态分配的内存或返回 与“free()”函数相同?

不,您需要通过调用

free
函数自行释放它。

这种释放分配内存的方式是否会产生内存泄漏的风险, 这是一个好习惯吗?

不,使用

free
没有风险,而且是非常好的做法

如果函数“test()”占用(并初始化)的内存是 由于它的执行结束而被释放,访问它并不危险 像代码示例中那样以这种方式处理地址?

当您从函数返回时,此内存不会被释放,并且在您自己“释放”它之前一直有效。

现代操作系统在程序终止时释放动态分配的内存,但

free
它们是一个好习惯。


1
投票

这是释放动态分配内存的好习惯吗?

是的。这是很好的做法。

代码检查了内存。 完成后放好 .

“由于执行结束而被释放”是一个糟糕的借口。将代码移植到不依赖它的更大任务更容易。

test()
应该清楚地记录它正在返回分配的内存,以后需要
free()
.


这些并没有改变上面的答案,但是 OP 示例代码中的问题掩盖了其他问题。

代码确实有其他薄弱或不良的做法:

缺乏错误检查

如果

malloc()
成功,更好的代码测试。

不需要演员

不需要转换

malloc()
的返回值。

没有检查

scanf()
的返回值。

更好的代码检查返回值。

引用对象的大小,而不是类型

在申报时分配

//  char *local_ptr = NULL;
// local_ptr = (char *)malloc(5*sizeof(char));

char *local_ptr = malloc(sizeof local_ptr[0] * 5);

迂腐:使用匹配说明符

%hhi
匹配
signed char *
。它可能会失败
char *
.

空间是多余的

scanf("%hhi",...
的表现与
scanf(" %hhi",...
一样,因为
%hhi
跳过前导空白。


0
投票

是的,虽然大多数现代操作系统会在程序终止时释放内存,但这并不是代码内存泄漏的借口。

还要注意

malloc()
和family的返回值不需要强制转换。这些函数返回隐式转换为任何其他指针类型的通用指针类型 (
void *
)。因此,它是多余的,只会使代码混乱。

#if 0
    char *local_ptr = NULL;
    local_ptr = (char *)malloc(5*sizeof(char));
#else
    char *local_ptr = malloc (5);
    if (!local_ptr) {
        complain();
    }
#endif

我们不需要

sizeof(char)
,因为它被标准定义为1并且首先声明和初始化指向
NULL
的指针没有意义,只是立即用
malloc()
的返回覆盖它。

© www.soinside.com 2019 - 2024. All rights reserved.