我对以下函数和内存分配有疑问。
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 推断这里会发生什么的能力。(它以某种方式认为跟踪 NULL
的 malloc
状态是相关的)。
如果您使用 latest GCC trunk 以最高优化级别编译此程序编译器会注意到所有的计算都是无用的并编译 a much simpler program :
int main(void) {
}
(请参阅中间 Pane 中的相同程序集)将具有 same observable behaviour , 但不调用 malloc
甚至一次。
关于c - 像这样在函数调用中分配的内存会发生什么变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55082531/