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()
.但这并不总是可行的.
(请注意,某些库会分配内存块,返回指向这些块的指针,并指示您释放它们.在这种情况下,您可以释放这些指针,但这对创建库的人来说是一个糟糕的设计实践. )
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->buffer
和globalBuffer
; 两者都指向独立于其中任何一个存在的同一事物. free
-ing container
不影响container->buffer
指向的字符串文字,因此printf(globalBuffer);
仍然显示"Test-string."
.
总之,你应该不叫
free(container->buffer);
Run Code Online (Sandbox Code Playgroud)
对于这个特殊程序,因为你没有分配的结果malloc
,calloc
或realloc
打电话给它.
如果,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
.