c - 像这样在函数调用中分配的内存会发生什么变化?

标签 c memory memory-leaks

我对以下函数和内存分配有疑问。

char    *strjoin(char const *s1, char const *s2)
{
    char    *s3;

    s3 = NULL;
    if (s1 && s2)
    {
        s3 = (char *)malloc(sizeof(char) * (strlen(s1) + strlen(s2) + 1));
        if (!s3)
            return (NULL);
        strcpy(s3, s1);
        strcat(s3, s2);
    }
    return (s3);
}

int main()
{
    char    *s1 = "my favorite animal is";
    char    *s2 = " ";
    char    *s3 = "the nyancat";
    char    *res = strjoin(strjoin(s1, s2), s3);
}

strjoins 文档如下:

Allocates (with malloc(3)) and returns a “fresh” string ending with ’\0’, result of the concatenation of s1 and s2. If the allocation fails the function returns NULL.

在主函数中,函数在这一行调用自身:

char *res = strjoin(strjoin(s1, s2), s3);

由于内存是在 strjoin(s1, s2) 中分配的,但从未分配给任何东西,并且它在外部函数调用中使用,但从技术上讲从未释放,那么该内存是否只是泄漏并未被使用?

最佳答案

是的,内部调用确实会泄漏内存。您可以通过将返回值存储在适当的位置来轻松避免泄漏:

char    *intermediate;
char    *res = strjoin(intermediate = strjoin(s1, s2), s3);
free(intermediate);

char    *intermediate = strjoin(s1, s2);
char    *res = strjoin(intermediate, s3);
free(intermediate);

但是内存会被操作系统释放main功能/当exit如果这是一个托管 系统,则调用。除非您正在对嵌入式设备、设备驱动程序或操作系统进行编程,否则您很可能以托管平台为目标。


现在,取决于编译器是否聪明,它实际上可能不会为该程序分配任何内存,因为不需要结果。

考虑稍作改动的程序:

#include <stdlib.h>
#include <string.h>

static inline __attribute__((always_inline)) char *strjoin(char const *s1, char const *s2)
{
    char    *s3; 
    s3 = NULL;

    if (s1 && s2) {
        s3 = malloc(strlen(s1) + strlen(s2) + 1);
        strcpy(s3, s1);
        strcat(s3, s2);
    }

    return s3;
}

int main()
{
    char    *s1 = "my favorite animal is";
    char    *s2 = " ";
    char    *s3 = "the nyancat";
    char    *res = strjoin(strjoin(s1, s2), s3);
}

我添加了 static inline __attribute__((always_inline))到函数,以便它只能在文件范围中看到,而不是从其他.c文件(它没有外部链接),并且该函数将始终内联到位;我还删除了 malloc 的返回值检查,因为它似乎阻碍了 GCC 推断这里会发生什么的能力。(它以某种方式认为跟踪 NULLmalloc 状态是相关的)。

如果您使用 latest GCC trunk 以最高优化级别编译此程序编译器会注意到所有的计算都是无用的并编译 a much simpler program :

int main(void) {
}

(请参阅中间 Pane 中的相同程序集)将具有 same observable behaviour , 但不调用 malloc甚至一次。

关于c - 像这样在函数调用中分配的内存会发生什么变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55082531/

相关文章:

c - 为什么输出之间存在差异?

c# - 未分配的属性会占用类中的内存吗?

objective-c - 为什么这个对象释放不正常,我应该释放它吗?

memory - 对象的 Redis 编码和大小影响

php - 如何修复 PHP 中的内存泄漏

delphi - 动态数组超出范围时是否会自动释放?

c - 对于缓冲区溢出,使用pthreads时栈地址是多少?

c - 数组订阅执行顺序

java - 已检测到内存泄漏但无法理解确切原因,因为 hashmap 条目令人困惑?

c++ - 使用枚举成员值检查变量值的优化方法