【问题标题】:Program should crash but it doesn't [duplicate]程序应该崩溃但它不会[重复]
【发布时间】:2020-07-21 06:47:54
【问题描述】:
#include <stdio.h>
#define CHAR_ROW_SIZE 4
int charTable[CHAR_ROW_SIZE ][2] = {
  {'X', 'Z'},
  {'J', 'L'},
  {'F', 'C'},
  {'A', 'B'}
};

int main()
{
    printf("char element %c\n", charTable[3][1]); //fine
    printf("char element %c\n", charTable[3][8]); // accessing 4th row's 9th element which is not valid 
    printf("char element %c\n", charTable[85][0]);// accessing 86th row's first element which is not valid 

    return 0;
}

输出:

char element B                                                                                                                                                                     
char element                                                                                                                                                                       
char element

据我了解,C\C++ 实际上并没有对数组进行任何边界检查。这取决于操作系统来确保您访问的是有效内存。所以这是未定义的行为。

但在这里我可以看到在另一台机器上的相同行为。即程序不会随时崩溃。

【问题讨论】:

标签: arrays c memory undefined-behavior


【解决方案1】:

但在这里我可以看到在不同的机器上不断出现相同的行为。即程序不会随时崩溃。

这里,崩溃(或分段错误)既不是期望的也不是保证的行为,行为是 undefined

这里的底线是,访问超出范围的内存(即,不属于您的进程地址空间的内存位置)是未定义的行为。有时带有 UB 的代码似乎工作得很好,没有任何分段错误,产生一些随机值,包括 0,造成事情“工作正常”的错觉,但事实并非如此!

【讨论】:

    【解决方案2】:

    除了那些调用abort(); 的程序之外,C 标准没有“应该崩溃”的程序的概念。编写 C 标准是为了允许实现以对编译器的客户最有用的任何方式处理越界数组访问。根据客户想要完成的任务,最有用的做法可能是:

    1. 在编译器可以识别出越界访问发生的情况下进行陷阱。
    2. 扩展语言的语义,这样如果程序员知道计算地址处的内容,代码就可以访问该对象并产生任何副作用[如果程序员不知道,代码无论如何都会访问它] .
    3. 执行访问而不考虑其有效性,但不允许访问可能与程序执行的其他操作交互。

    在编写标准时,存在以所有三种方式运行的实现,以及三种方式中的每一种都最有用的程序。该标准的作者并没有试图对在任何特定情况下哪种方法最好做出任何判断,而是希望任何希望出售编译器的人都会寻求以他们的客户认为最有用的任何方式来处理代码——这是一种行之有效的哲学好吧,当语言趋势由对客户利益负责的编译器编写者推动时。

    【讨论】:

      猜你喜欢
      • 2014-07-17
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 2011-12-30
      • 1970-01-01
      • 2015-03-31
      相关资源
      最近更新 更多