我需要为研究项目学习C ++基础知识,并且我正在尝试错误/异常处理。我成功地使用throw
命令来预测可能发生的事件(例如除以零),但我无法弄清楚如何捕获意外的异常。以此示例代码为例:
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;
void arrayOutOfBound()
{
int a[3] = {1, 2, 3};
try
{
cout << "This should not display: " << a[5] << endl;
}
catch(runtime_error &e)
/* catch(exception &e) // also does not work */
{
cout << "Error: " << e.what() << endl;
}
}
int main()
{
arrayOutOfBound();
}
我想我必须在某处使用throw
语句,但是假设我真的不知道a[5]
不起作用(或者用户输入了这个索引而我没有检查数组大小),那么如何防止程序崩溃? (因为这在Visual C ++ Express 2010调试器中发生)
注意:如果我首先在块之外执行try { int result = a[5]; }
,并在最后尝试使用cout << result
,则程序不会编译。编译器试图帮助我,但因此我无法尝试异常处理。
答案 0 :(得分:3)
假设我真的不知道[5]不起作用(或者用户输入了这个索引而我没有检查数组大小),那么如何防止程序崩溃呢?
你根本做不到。对数组的越界访问导致C ++中的未定义行为,它不会引发异常。当你足够幸运时,你会崩溃。
答案 1 :(得分:2)
抱歉无法抗拒引用一个明显的模因“原生阵列......那不是你怎么做的!” :d
您上面编写的代码使用的本机数组本质上是一个内存位置。所以说[5]你说我想把地址上的4个字节(a + 4 * sizeof(int))解释为int。这不会引发异常。它是未定义的行为,可能会返回垃圾。如果你使用-O2或一些这样的编译器标志,它可以返回0和顺便说一下,这是缓冲区溢出的A级来源:D
这是一个可以解决问题的模板类:
#include <iostream>
#include <exception>
#include <stdexcept>
#include <vector>
using namespace std;
template<class T, size_t COUNT>
class CheckedArray
{
public:
class OutOfBounds : public std::exception
{
public:
virtual const char* what() const throw(){ return "Index is out of bounds"; }
};
CheckedArray(){}
virtual ~CheckedArray(){}
const T& operator[] (size_t index) const
{
if(index >= COUNT){ throw OutOfBounds(); }
return m_array[index];
}
T& operator[] (size_t index)
{
if(index >= COUNT){ throw OutOfBounds(); }
return m_array[index];
}
private:
T m_array[COUNT];
};
void arrayOutOfBound()
{
//int a[3] = {1, 2, 3};
CheckedArray<int,3> a;
a[0] = 1;
a[1] = 2;
a[2] = 3;
try
{
cout << "This should not display: " << a[5] << endl;
}
catch(std::exception& e) // this will kick in
{
cout << "Error: " << e.what() << endl;
}
}
int main()
{
arrayOutOfBound();
}
答案 2 :(得分:1)
如果您需要此行为,建议您编写一个类,例如“CheckedArray”包装数组并执行边界检查。如果你完全通用,它将是一个模板类,你当然需要知道重载operator []。
或者,如果您对动态分配的数组的开销感到满意,请使用std::vector
,特别是其at
成员函数会在超出范围的索引上引发异常。作为附带好处,您的阵列现在可以在运行时(重新)调整大小。
更好的是,使用std::array
同时具有抛出at
功能(但不可调整大小。)
答案 3 :(得分:1)
如果您使用std::array
(而不是C样式数组)和.at()
成员函数
std::array <int, 5> stdArray = {1, 2, 3, 4, 5};
//array boundary check
try {
cout << "trying to access out of bound element " << endl;
cout << stdArray.at(5) << endl;
} catch(std::exception &e) {
cout << "Error: " << e.what() << endl;
}
现在程序不会崩溃,而是看到此输出
Error: array::at: __n (which is 5) >= _Nm (which is 5)
答案 4 :(得分:0)
如果你只想要一个处理器来处理分段错误等,你应该查看signal.h
//约翰