为啥尝试更改 _arr[3] 时没有抛出异常?

Posted

技术标签:

【中文标题】为啥尝试更改 _arr[3] 时没有抛出异常?【英文标题】:Why is there no exception thrown when trying to change _arr[3]?为什么尝试更改 _arr[3] 时没有抛出异常? 【发布时间】:2019-07-19 10:47:38 【问题描述】:

我有这段代码,它应该在尝试到达 Container 中 _arr 的第三个索引时抛出异常。它没有抛出异常,我不明白为什么。

移除构造函数会导致它抛出异常,这真的很奇怪。

class X 
public:
    X(int x)  std::cout << x - 1; 
;

template <class T, int d=3>
class Container 
    T* _arr;
public:
    Container():_arr(new T[d]) 
    void setItemAtIndex(T item, int index)  _arr[index] = item; 
    X getItemAtIndex(int index)  return _arr[index]; 
;

int main()

    Container<int> container;
    for (int i = 1;i < 4;i++) 
        container.setItemAtIndex(i, i);
        X x = container.getItemAtIndex(i);
    
    return 0;
    

我预计会抛出异常,但它实际上输出“012”。

【问题讨论】:

C++ 不检查数组边界。您需要在setItemAtIndexgetItemAtIndex方法中自行添加校验码。 未定义的行为不会引发异常。或者至少,这不是一个明确的原因。未定义的行为原则上可以做任何事情。 您的 setItemAtIndex 和 getItemAtIndex 缺少检查索引是否在范围内,如果不在范围内则抛出异常。 感谢您的回复。考虑到我在 Visual Studio 中遇到的情况,我认为更改未专门分配给数组(索引 3)的内存将是运行时错误。 【参考方案1】:

C++ 遵循哲学(尽管有些例外违反了它)“不要为不需要的东西买单”。在超出数组边界时抛出异常需要显式检查。但是如果你已经知道不能超过?

for(size_t i = 0; i < sizeof(someArray)/sizeof(*someArray); ++i)
    someArray[i] = 0; // i CANNOT be outside array boundaries, so why check???

这使得 C++ 速度更快,但另一方面,如果它们 是必要的(就像在您的访问器函数中一样),则会将这些检查强加给 。正是出于这个原因,std::vector 提供了operator[](未选中)和at(选中,超过当前大小时抛出异常)。

如果您越界访问数组,就会调用未定义的行为。您可能会逃脱,因为可能会与您的数组一起分配一些额外的内存。如果您超出数组边界足够,您可能会看到与省略构造函数时相同的“异常”(使指针未初始化为某个随机值)。实际上,这在 C++ 意义上并不是一个例外。这是访问冲突(读取您的程序不存在或无法访问的内存地址),很可能由您的操作系统检测到,它通过某种适当的方式处理该问题(例如,linux 向您的程序发送 SIG_SEGV 信号)。

【讨论】:

感谢您的回复。另一个快速的问题,访问冲突不应该导致运行时错误吗? @tempt 好吧,是在程序执行期间读取或分配指针,不是吗?此外,当你的程序执行时,指针的有效性可能随时改变,编译器应该如何检测呢?只是读取或写入无效地址本身已经是错误,是的,运行时错误......【参考方案2】:

C++ 中没有规定在越界访问数组时必须抛出异常。这只是undefined behaviour的一个案例。

移除构造函数会导致它抛出异常,这真的很奇怪。未定义的行为是不可预测的。我猜你的系统最好设置为通过未初始化的指针捕获访问,而不是对数组的越界访问。

【讨论】:

以上是关于为啥尝试更改 _arr[3] 时没有抛出异常?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不可能从 __toString() 抛出异常?

为啥我应该在抛出异常指针时使用按引用捕获

如果实体中没有getter和setter,为啥hibernate不会抛出异常

为啥在析构函数中抛出异常时不调用重载删除?

为啥某些带有双反斜杠的路径抛出找不到路径异常的一部分?

为啥非空列表会抛出空指针异常?