我免费的char *应使用初始化的字符串字面量? [英] Should I free char* initialized using string-literals?

查看:92
本文介绍了我免费的char *应使用初始化的字符串字面量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我应该释放的char * 变量的时候,他们用字符串初始化了?对我来说,语法将导致我,他们只是堆栈分配的假设,但这个例子给我看,他们不是。

 的#include<&stdlib.h中GT;
#包括LT&;&stdio.h中GT;静态字符* globalBuffer;typedef结构{集装箱
    字符*缓冲区;
} 容器;集装箱* Container_new(字符*缓冲区){
    集装箱货柜* malloc的=(的sizeof(容器));
    盛载>缓冲区=缓冲区;
    globalBuffer =缓冲;
    返回容器中;
}无效Container_print(集装箱货柜*){
    如果(盛载>!缓冲= NULL){
        的printf(盛载>缓冲区);
        的printf(\\ n);
    }
    其他{
        的printf(容器包含NULL缓冲器。);
    }
}容器*阶段(){
    集装箱货柜* = Container_new(测试字符串。);
    Container_print(容器);
    返回容器中;
}诠释主(){
    集装箱货柜* =阶段();
    Container_print(容器);    免费(容器);
    Container_print(容器); //我知道,这会导致不确定的行为    的printf(globalBuffer);
    的printf(\\ n);    返回0;
}

我得到以下的输出:

  C:\\用户\\尼克拉斯\\桌面> GCC char_test.cC:\\用户\\尼克拉斯\\桌面> A.EXE
测试串。
测试串。
6个
测试串。C:\\用户\\尼克拉斯\\桌面>

因此​​,的char * 与字符串字面量初始化确实还存在,即使它得到了超出范围。

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

  INT的main(){
    集装箱货柜* =阶段();
    Container_print(容器);    免费(盛载>缓冲区); // NEW
    免费(容器);
    Container_print(容器);    的printf(globalBuffer);
    的printf(\\ n);    返回0;
}


解决方案

字符串字面存储在这样一种方式,他们提供了该程序的生命周期;如果你写

 的char * PTR =这是一个测试;

所有的写入 PTR 地址的字符串字面量这是一个测试。即使 PTR 变量超出范围,字符串继续在自己的存储单元,这是存在的的使用的同款通过的malloc (至少不是在逻辑电平)。注相同的字符串的多个实例的可能的解析为相同的位置; IOW,鉴于

 的char * P0 =这是一个测试;
字符* P1 =这是一个测试;

P0 P1 可能都包含相同的地址(它是由编译器是否字符串文字的多个实例被映射到相同的位置,或者不是)。

当你调用 Container_new ,你正在做的是一个复制的地址盛器>缓冲区 globalBuffer ;这两个风指着存在的其中任何一个独立的同样的事情。 免费 -ing 容器不影响字符串的盛器>缓冲区点,所以的printf(globalBuffer); 仍显示测试字符串

总之,您应该的的通话

 免费(盛器>缓冲区);

对于这个特殊程序,因为你没有指定的malloc 释放calloc 或结果的realloc 调用它。

如果,OTOH,你写 Container_new

 集装箱* Container_new(字符*缓冲区)
{
  集装箱货柜* malloc的=(的sizeof(容器));
  盛载&GT缓冲液= malloc的(strlen的(缓冲器)+1); //分配内存
  如果(盛载>缓冲区)//存储*新的*实例
  输入字符串的{//。
    的strcpy(盛载>缓冲区,缓冲区); //这将需要
  } //释放之前释放
  globalBuffer =缓冲; //容器
  返回容器中;
}

那么你的 的需要自由盛器>缓冲区释放之前容器

Should I free char* variables when they were initialized using string literals? To me, the syntax would lead me to the assumption that they are only stack-allocated, but this example showed me, they are not.

#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(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;
}

I get the following output:

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>

So, the char* initialized with string-literals does still exist, even it got out of scope.

So, my question, should I free such char* pointers? Would this be the correct main()?

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

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

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

    return 0;
}

解决方案

String literals are stored in such a way that they're available for the lifetime of the program; if you write

char *ptr = "This is a test";

all that's written to ptr is the address of the string literal "This is a test". Even if the ptr variable goes out of scope, the string literal continues to exist in its own section of memory, which is not the same section used by malloc (at least, not at a logical level). Note that multiple instances of the same string literal may resolve to the same location; IOW, given

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

p0 and p1 may both contain the same address (it's up to the compiler whether multiple occurrences of string literals are mapped to the same location or not).

When you call Container_new, all you're doing is copying an address to container->buffer and globalBuffer; both wind up pointing to the same thing that exists independently of either of them. free-ing container doesn't affect the string literal that container->buffer points to, so printf(globalBuffer); still displays "Test-string.".

In summary, you should not call

free(container->buffer);

for this particular program, since you didn't assign the result of a malloc, calloc, or realloc call to it.

If, OTOH, you had written Container_new as

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;
}

then you would need to free container->buffer before freeing container.

这篇关于我免费的char *应使用初始化的字符串字面量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆