1

所以我的理解是,一个 C 字符串,例如“0123456789”,实际上会占用一个由 11 个字符组成的数组,其中 10 个字符用于正文,一个字符用于终止 null。如果这是真的,那么为什么下面的代码不会导致某种错误?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char ** argv){

    char * my_string = "0123456789";
    /* my string should occupy 11 bytes */

    int my_len = strlen(my_string);
    /* however, strlen should only return 10, 
        because it does not count the null byte */

    char * new_string = malloc(my_len);
    /* allocate memory 10 bytes wide */

    memcpy(new_string, my_string, my_len);
    /* copy the first 10 bytes from my_string to new_string
        new_string should NOT be null terminated if my understanding
        is correct? */

    printf("%s\n", new_string);

    /* Since new_stirng is NOT null terminated it seems like this should
        cause some sort of memory exception.
        WHY DOES THIS NOT CAUSE AN ERROR?

    */

    return 0;
}

由于new_string不是空终止,我希望printf永远读取,直到它到达一些其他应用程序内存,或者随机放置在某处的 0x00 并且崩溃或打印一些奇怪的东西。这是怎么回事?

4

5 回答 5

4

您创建了未定义的行为。该行为取决于编译器和平台。它可能会崩溃。它可以工作。它可以让你敬酒。它可能会将您的计算机坍塌成一个奇点并吸收太阳系。

在您的情况下,内存可能new_string[11]已经0是 ,即'\0',或者终止空字符。

于 2012-06-01T20:48:45.053 回答
3

因为它是未定义的行为。未定义的行为并不意味着段错误,尽管这是一种可能性。

于 2012-06-01T20:46:47.613 回答
3

在您的情况下,您从 malloc 获得的特定内存块以前从未使用过(由您的程序),并且它可能在分配时被操作系统零初始化。因此,第 11 个字节可能为零,因此没有错误。在运行时间较长的程序中,malloc 可能会返回第 11 个字节不为 0 的脏内存块,因此您将在 printf 语句中遇到问题。在实践中,如果在分配区域结束之前没有空值,您将打印垃圾(直到遇到第一个空值)或段错误。

(正如其他人所说,这种行为在形式上是未定义的,我只是在解释你所看到的)。

于 2012-06-01T20:51:06.787 回答
1

或随机放置的 0x00 某处...打印一些奇怪的东西。

这是通常观察到的行为。实际会发生什么是不确定的。

于 2012-06-01T20:47:21.267 回答
0

这是未定义的行为。在某些情况下,它可能会导致崩溃,这取决于我想象的内存布局

于 2012-06-01T20:51:01.160 回答