为什么打印出“test”?:
char *str;
str = (char *)malloc(1);
str[0] = 't';
str[1] = 'e';
str[2] = 's';
str[3] = 't';
我正在尝试动态扩展字符串并尝试理解malloc / realloc是如何工作的,上面的行为让我感到困惑,因为malloc()/ realloc()建议扩展char *。
提前致谢。
答案 0 :(得分:4)
未定义的行为意味着任何事情都可能发生。包括出现“工作”,什么都没有,或者是分段错误。您的示例代码确实很糟糕,但C标准并不保证它会做任何“有用”的事情,也不保证在编译时或运行时都会发生任何“坏”。
答案 1 :(得分:2)
您正在撰写超出“正式”分配内存的末尾。大多数内存分配系统都具有内部使用的最小大小,并且您可能实际上并未超出那个边界,因此您的代码似乎正在运行。如果你让字符串足够长,你最终会传递一个对操作系统很重要的边界,你的程序就会崩溃。
您可以为str
分配一个随机数,然后将其视为指针,并且每隔一段时间它就会真正起作用。但你不知道你可能会写什么。与你的记忆超限相同。内存分配器可以紧密地打包分配,以便您覆盖程序中的其他内容。
你应该总是确保你不会超出任何数组的范围。的 EVER 即可。缓冲区溢出(和欠载)正是许多黑客利用它们进入系统的原因。确保你不允许它们,并且你已经在那里有相当多的旧代码了。
答案 2 :(得分:1)
这段代码显然是错误的 - 很明显 - 你正在通过数组边界访问内存。
它有效,因为:
没有机制来检测每个无效的内存访问。许多这样的尝试会导致分段错误,但每次都不会发生。很多时候这样的错误代码只是覆盖了一些随机变量等等 - 这就是为什么像这样的调试问题很快就会成为一场噩梦的原因之一。我建议你熟悉Valgrind。
在这种特殊情况下,我会说malloc()
将分配的内存块四舍五入到(至少)4的倍数,所以在这种情况下它可能会按预期工作。但它仍然是一个错误。
你也没有明确地终止字符串,而且 - 行为实际上是随机的,str[4]
可以有任何价值。它取决于很多东西 - 从堆分配器实现到纯巧合。