【问题标题】:Why does this program NOT segfault? [duplicate]为什么这个程序没有段错误? [复制]
【发布时间】:2020-09-20 14:03:51
【问题描述】:

通常,这个问题可能会以积极的方式表达,成为重复问题俱乐部中的下一个成员 - 希望这个不是。我写了一个简单的程序来反转 C 中的字符串。这里是:

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

int main(void) {
    char arr[4] = "TEST";
    char rev[2];

    int j = 0;
    for(int i = 0; i < 4; i++) {
        j = 4 - i - 1;
        rev[j] = arr[i]; 
    }

    printf("%s\n",rev);
}

当我将 char arrchar rev 定义为 4 时,一切正常。当我离开arr 尺寸时,我得到了意想不到的重复输出,如“TSTTST”。当我将 rev 定义为 2 个字符的数组时,我没有收到段错误,但在循环中我试图访问它的第三个和第四个元素。据我相对有限的理解告诉我,访问长度为 2 的数组中的第三个元素应该是段错误,对吧?那为什么不呢?

编辑:

有趣的是,当我像这样离开循环时

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

int main(void) {
    char arr[4] = "TEST";
    char rev[2] = "00";

    printf("%s\n",rev);
}

它打印“00TEST”。这里发生了什么?某种溢出?我什至重新启动了终端,重新编译并再次运行。

编辑 2:

我已经知道这确实是重复的。但是,大多数建议的重复项都提到了 C++,而事实并非如此。我认为对于新的 C 程序员来说,这是一个学习和理解未定义行为的好问题。一方面,我不知道越界访问数组总是会导致 SEGFAULT。 另外,我了解到我必须自己终止字符串文字,我错误地认为这是自动完成的。这部分是错误的:它是自动添加的 - C99 标准 (TC3) 在 6.4 中说.5 在翻译阶段 7 添加终止空值的字符串文字。根据this answer 和此问题的答案,char 数组也是空值终止的,但这只有在数组具有正确长度时才是安全的(字符串长度 + 1 为空终止符)。

【问题讨论】:

标签: c


【解决方案1】:

char rev[2] 使用变量/指针rev 分配大小为2*sizeof(char) 的内存。您正在访问未分配给指针的内存。它可能会也可能不会导致错误。

它可能看起来工作正常,但它根本不是很安全。通过在分配的内存块之外写入数据,您正在覆盖一些您不应该覆盖的数据。这是导致段错误和其他内存错误的最大原因之一,而您所观察到的在这个简短的程序中似乎可以工作,这使得追查根本原因变得如此困难。

当您执行rev[2] or rev[3] 时,您正在访问未分配给rev 指针的rev + 2rev + 3 地址。由于它是一个小程序,并且没有任何内容,因此不会导致任何错误。

关于编辑:

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

int main(void) {
    char arr[4] = "TEST";
    char rev[2] = "00";

    printf("%s\n",rev);
}

%s 打印直到遇到 null,您分配的 arrrev 的大小不允许 null 存在,请尝试按以下方式更改值:

    char arr[5] = "TEST";
    char rev[3] = "00";

程序将按预期工作,如arr 中的TEST\0rev 将是rev\0 其中\0 是C 中的空字符。

阅读此article,它将解决您的大部分问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-07
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    相关资源
    最近更新 更多