这个问题旨在加深我对
的理解
分配和释放时我可以对指针做什么和不能做什么:
下面的代码并不意味着要运行,而只是为下面的问题设置一个情况。
char *var1 = calloc(8,sizeof(char));
char **var2 = calloc(3,sizeof(char*));
var1 = "01234567";
var1[2] = '\0';
var1[5] = '\0';
//var1 = [0][1][\0][3][4][\0][6][7]
var2[0] = var1[0];
var2[1] = var1[3];
var2[2] = var1[6];
free(var1);
free(var2);
给出以下代码片段
1:如果您知道分配的大小,是否可以写入\0 之后的位置。
2:如果 var2 指向另一个指针所指向的 block ,我可以执行我对 var2 所做的操作吗?
3:免费电话可以吗?或者会由于 var1 中的\0 而自由死亡。
我在释放后打印出了所有变量,并且只有第一个 null 之前的变量被释放(更改为 null 或其他奇怪且正常的字符)。这样可以吗?
4:您希望指出的任何其他完全错误的内容应该避免。
非常感谢。
最佳答案
好的,让我们回顾一下您在这里所做的事情:
char *var1 = calloc(8,sizeof(char));
char **var2 = calloc(3,sizeof(char*));
因此,var1
是(指向)8 个字符的 block ,全部设置为零\0
。
var2
是(指向)3 个指针的 block ,全部设置为 NULL。
现在它是程序的内存,它可以用它做任何它想做的事。
专门回答你的问题~
在 char block 内写入字符是很正常的。这是一种常见的编程模式,通过在一段文本后写入 \0
来对其使用日常 C 字符串操作来解析字符串缓冲区,然后指向添加的 \0 之后的下一个字符
并继续解析。
var2
只是一堆字符指针,它可以指向任何需要的字符,它不一定必须位于字符串的开头。
对 free()
的调用有些正常(除了错误 - 见下文)。 free()d block 的内容在返回到堆栈时被覆盖是正常的,因此如果之后打印出来,它们通常看起来有“垃圾”字符。
var1
的分配存在一些问题 ~
var1 = "01234567";
这里你说的是“var1现在指向这个常量字符串”。您的编译器可能已生成有关此的警告。首先,代码将 const char*
分配给 char*
(硬编码字符串是 const,但 C 编译器只会对此发出警告 [编辑:这对于 C++ 来说是正确的) ,而不是 C,请参阅 n.m. 的评论])。其次,代码丢失了对var1
用来指向的内存块的所有引用。现在你永远不能free()
这 block 内存了——它已经泄漏了。然而,在程序结束时,free()
尝试操作指向未在堆上分配的内存块(“01234567”)的指针。这不好。由于您立即退出,因此不会产生任何不良影响,但如果这是在执行过程中,则下一个分配(或下一个第 1000 个!)可能会奇怪地崩溃。这类问题很难调试。
也许你应该在这里做的(不过我猜你的意图)是使用字符串副本:
strncpy(var1, "01234567", 8);
通过该操作而不是赋值,一切正常。这是因为数字存储在第 1 行分配的内存中。
关于C 通过 char* 正确处理空终止符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53383804/