2

为什么这会打印出“测试”?:

    char *str;
    str = (char *)malloc(1);
    str[0] = 't';
    str[1] = 'e';
    str[2] = 's';
    str[3] = 't';

我正在尝试动态扩展字符串并尝试了解 malloc/realloc 的工作原理,而上述行为让我感到困惑,因为 malloc()/realloc() 建议扩展 char* 。

提前致谢。

4

3 回答 3

4

未定义的行为意味着任何事情都可能发生。包括看起来“工作”,什么都没有,或分段错误。您的示例代码确实很糟糕,但 C 标准不保证它会做任何“有用”的事情,也不保证在编译时或运行时一定会发生任何“坏事”。

于 2013-03-12T19:02:20.660 回答
2

您正在写超出“正式”分配的内存的末尾。大多数内存分配系统都有内部使用的最小大小,您可能实际上并没有超出边界,因此您的代码似乎可以正常工作。如果你让字符串足够长,你最终会传递一个对操作系统很重要的边界,你的程序就会崩溃。

您可以分配一个随机数str,然后也将其视为一个指针,并且每隔一段时间它就会真正起作用。但是你不知道你可能在写什么。与您的内存溢出相同。内存分配器可能会将分配打包得足够紧,以至于您正在覆盖程序中的其他内容。

您应该始终确保您不会超出任何数组的范围。 曾经。缓冲区溢出(和欠载)正是许多黑客利用来侵入系统的原因。确保您不允许它们,并且您已经比那里的大量旧代码更好。

于 2013-03-12T19:05:59.330 回答
1

显然,这段代码是完全错误的——您正在访问超出数组边界的内存。

它有效,因为:

  • 没有适当的机制来检测每一个无效的内存访问。许多此类尝试会导致分段错误,但并非每次都发生。很多时候,这样的错误代码只是简单地覆盖了一些随机变量等——这就是为什么像这样的调试问题会很快成为一场噩梦的原因之一。我建议您熟悉Valgrind

  • 在这种特殊情况下,我会说malloc()将分配的内存块四舍五入到(至少)4的倍数,所以在这种情况下它可能会按预期工作。但它仍然是一个错误。

  • 你也没有明确地终止字符串,而且再次 - 行为真的是随机的,真的str[4]可以有任何价值。这取决于很多事情——从堆分配器的实现到纯粹的巧合。

于 2013-03-12T19:06:32.060 回答