为字符串动态分配内存

Allocating memory for strings dynamically

char* test() {
    char* returnValue = "test";
    return returnValue;
}  
char* test=test();
printf("%s",test);

使用安全吗?和

一样吗
char* test {
    char* returnValue=strdup("test");
    return returnValue;
}
char* test=test();
printf("%s",test);

如果是,那我应该稍后释放它吗?它们似乎都能正常工作。

is it the same

不,不是。


char * test1() {
  char * returnValue = "test";
  return returnValue;
}  

上面的代码returns固定地址到常量文字"test"。每次调用该函数时,这将是 相同的 地址。

它是不是内存的动态分配

正在做

printf("%d\n", test1() == test1());

将打印

1

表示"true",返回的两个地址相同

关于“常量

为了更好地反映test1()结果的常量性,最好定义如下:

const char * test1() {
  const char * returnValue = "test";
  return returnValue;
}  

char * test2 {
  char * returnValue = strdup("test");
  return returnValue;
}

上面的代码 returns 新分配的 内存区域的地址已被复制 "test" 到。每次调用该函数时,这将是一个 不同的*1 地址。

*1:至少"different",只要之前任何调用test2()[的结果=80=] 尚未被 free() 编辑

这个内存的动态分配。因此,如果不再需要,它需要调用 free() 传递 strdup() (which internally calls malloc()) 返回的地址来释放内存。

正在做

printf("%d\n", test2() == test2()); /* leaks memory: 2 times 4+1 char */

将打印

0

表示"false",返回的两个地址不同

为了完整性:按照上面的代码片段避免泄漏

char * p, * q;
printf("%d\n", (p = test2()) == (q = test2()));
free(p);
free(q);

is it saft to use

形式上,两个片段的代码都是正确的。

使用哪个以及是否使用 "safe" 完全取决于用例,取决于上下文。

is it safe to use?

是的,除非您尝试更改字符串。实际上没有分配,所以每次你的函数都会 return 完全相同的指针指向内存中的相同位置。

is it the same, as

不,strdup() 进行了分配并且 return 分配了新的内存。

if yes, then should I free it later on?

不是,不过strdup()之后你还是需要释放内存。

they are both seem to work correctly

对于 printf() 没问题,除非您尝试更改这些字符串...您将无法更改 char* returnValue = "test" 字符串,但您可以更改之后的字符串strdup()

char* test() {
    char* returnValue = "test";
    return returnValue;
}  

is it safe to use?

是的,只要您不尝试修改 returnValue,它是一个 字符串文字 。字符串文字具有静态存储持续时间,因此它们 在程序的整个生命周期中都是有效的 但尝试修改字符串文字的内容是未定义的行为。

is it the same, as

char* test {
    char* returnValue=strdup("test");
    return returnValue;
}

答案是 -

strdup()

Returns a pointer to a null-terminated byte string, which is a duplicate of the string pointed to by str1. The returned pointer must be passed to free to avoid a memory leak.

strdup()使用malloc()为新字符串获取内存,这里新字符串为"test"它一直保持分配状态,直到它被显式释放或直到程序结束。因此,完成后应该使用 free() 释放它。此外,您可以修改 strdup() 返回的字符串的内容,但请确保不要访问超出分配的内存块。

在这两种情况下,"test" 堆栈 中分配为内存的只读部分 (const char)。

在第一个块中,您 return 指向 "test" 的指针。如前所述,这在函数调用中始终是相同的值。由于它是只读的 属性,尝试释放或修改它时,将引发执行错误(尝试释放时 munmap_chunk(): invalid pointer,尝试释放时 Segmentation fault修改).

在第二个块中,您 return 指向 中动态分配的内存部分的指针。您有责任使用 free() 或等效方法释放这部分内存。您可以随意修改这个变量,甚至重新分配这部分内存。

您可以随时进行自己的测试:

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

char* test1() {
    char* returnValue = "test";
    return returnValue;
}  
char* test2() {
    char* returnValue = strdup("test");
    return returnValue;
}

int main(void)
{
   char* vtest1 = test1();
   printf("%s => %p\n", vtest1, &vtest1);
   char* vtest2 = test2();
   printf("%s => %p\n", vtest2, &vtest2);

   printf("Freeing 2nd test...\n");
   free(vtest2);

   printf("Trying to modify 1st test...\n");
   vtest1[0] = 'p';
   printf("Freeing 1st test...\n");
   free(vtest1);

   return 0;
}