我应该使用字符串文字来释放char*吗?

Nik*_*s R 20 c memory memory-management

我应该char*在使用字符串文字初始化时自由变量吗?对我来说,语法会让我假设它们只是堆栈分配,但这个例子告诉我,它们不是.

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

static char* globalBuffer;

typedef struct Container {
    char* buffer;
} Container;

Container* Container_new(char* buffer) {
    Container* container = malloc(sizeof(Container));
    container->buffer    = buffer;
    globalBuffer         = buffer;
    return container;
}

void Container_print(Container* container) {
    if (container->buffer != NULL) {
        printf("%s", container->buffer);
        printf("\n");
    }
    else {
        printf("Container contains a NULL-buffer.");
    }
}

Container* stage() {
    Container* container = Container_new("Test-string.");
    Container_print(container);
    return container;
}

int main() {
    Container* container = stage();
    Container_print(container);

    free(container);
    Container_print(container); // I know, this results in undefined behaviour

    printf(globalBuffer);
    printf("\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

C:\Users\niklas\Desktop>gcc char_test.c

C:\Users\niklas\Desktop>a.exe
Test-string.
Test-string.
­6>
Test-string.

C:\Users\niklas\Desktop>
Run Code Online (Sandbox Code Playgroud)

因此,char*使用字符串文字初始化仍然存在,即使它超出了范围.

所以,我的问题,我应该释放这样的char*指针吗?这是正确的main()吗?

int main() {
    Container* container = stage();
    Container_print(container);

    free(container->buffer);    // NEW
    free(container);
    Container_print(container);

    printf(globalBuffer);
    printf("\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Adr*_*son 31

你永远不会free()忘记你没有malloc()编辑.

编译器实现字符串文字的方式不是您的业务:它是一个实现细节.您可以free()使用指向您使用的内存的指针malloc(),只有那些,或者您正在冒着系统生命的风险.

理想情况下,malloc()调用和free()调用应该出现在相同的"设计级别"(例如,在相同模块的相同实现文件中),并且它们应该完美匹配:free()每个一个malloc().但这并不总是可行的.

(请注意,某些库会分配内存块,返回指向这些块的指针,并指示您释放它们.在这种情况下,您可以释放这些指针,但这对创建库的人来说是一个糟糕的设计实践. )

  • @Mysticial:C标准库是糟糕设计的一个很好的例子...... (5认同)
  • 如果图书馆的设计不好给你指针并告诉你在你不再需要它们时释放它们......处理库释放内存的正确方法是什么? (3认同)
  • @SzerémiAttila:库应该为您提供函数调用以释放它已分配的内存.这确保调用正确的函数来释放指针(取决于所使用的运行时和库的链接方式,`malloc()`和`free()`在库内部或外部可能不一样) (3认同)
  • 好吧,如果你要抱怨“strdup”,你也可以抱怨“calloc”和“realloc”...... (2认同)

Joh*_*ode 31

字符串文字的存储方式使它们在程序的生命周期内可用; 如果你写

char *ptr = "This is a test";
Run Code Online (Sandbox Code Playgroud)

所有写的ptr都是字符串文字的地址"This is a test".即使ptr变量超出范围,字符串文字继续在其自己的存储部分,其存在通过所使用的相同的部分malloc(至少,不在逻辑电平).请注意,同一字符串文字的多个实例可能会解析到同一位置; 我,给定

char *p0 = "This is a test";
char *p1 = "This is a test";
Run Code Online (Sandbox Code Playgroud)

p0并且p1可能都包含相同的地址(由编译器决定是否将多次出现的字符串文字映射到同一位置).

当你打电话时Container_new,你所做的只是将地址复制到container->bufferglobalBuffer; 两者都指向独立于其中任何一个存在的同一事物. free-ing container不影响container->buffer指向的字符串文字,因此printf(globalBuffer);仍然显示"Test-string.".

总之,你应该

free(container->buffer);
Run Code Online (Sandbox Code Playgroud)

对于这个特殊程序,因为你没有分配的结果malloc,callocrealloc打电话给它.

如果,OTOH,你写的Container_new

Container* Container_new(char* buffer) 
{
  Container* container = malloc(sizeof(Container));
  container->buffer    = malloc(strlen(buffer) + 1);  // Allocate memory to 
  if (container->buffer)                              // store a *new* instance
  {                                                   // of the input string. 
    strcpy(container->buffer, buffer);                // This will need to be 
  }                                                   // freed before freeing
  globalBuffer         = buffer;                      // the container
  return container;
}
Run Code Online (Sandbox Code Playgroud)

那么你需要释放container->buffer释放之前container.