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

时间:2012-02-29 18:26:34

标签: 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;
}

我得到以下输出:

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>

因此,使用字符串文字初始化的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;
}

2 个答案:

答案 0 :(得分:30)

你永远不会free()记忆你没有malloc()编辑。

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

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

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

答案 1 :(得分:30)

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

char *ptr = "This is a test";

所有写入ptr的内容都是字符串文字"This is a test"地址。即使ptr变量超出范围,字符串文字也会继续存在于其自己的内存部分中,而不是 malloc使用的相同部分(至少,而不是在逻辑层面)。请注意,同一字符串文字的多个实例可以解析到同一位置; IOW,给出

char *p0 = "This is a test";
char *p1 = "This is a test";

p0p1可能都包含相同的地址(由编译器决定是否多次出现字符串文字到同一位置)。

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

总之,您应该致电

malloc

此特定程序,因为您未将callocreallocContainer_new调用的结果分配给它。

如果,OTOH,您已将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; } 写为

container->buffer

然后你 需要在释放container之前释放{{1}}。