当数组超出范围时,通过异常检查是否安全?
Is checking by an exception safe for when array goes out bound?
这是我的代码:
template<class T>
void Matrix<T>::set(const int i, const int j, const T v) {
try {
m[i][j] = v;
} catch (std::exception& e) {
std::cout << "Standard exception: " << e.what() << std::endl;
}
}
可是,我这里安全吗?我的意思是,有可能 i
and/or j
超出了范围,但是程序接收到分段错误,然后会抛出异常吗?
如果这不是一个好方法,那么我应该使用 assert()
吗?
只需添加边界检查。
C++ 不对数组进行边界检查,更不用说抛出异常了。
使用 vectors/std::array,您可以使用 .at()
方法而不是 []
运算符来进行检查。
最后,GSL 引入了 array_view
,它允许您添加 "zero cost annotation",以便分析工具可以进行边界检查。目前还没有出现 GSL 的实际标准实现。另见:
没有
仅从数组读取时,异常检查可能还可以(但一点也不优雅)。
然而,在写入时,您可能会覆盖 "foreign" 内存,这是一个巨大的安全风险,而且它可能会通过覆盖堆栈帧来改变执行流程,谁知道呢 - 也就是说,肯定存在某些情况当异常处理程序不会 运行 时,即使它实际上应该抛出。
最好的决定是在每次迭代时检查索引。
鉴于您提到了 assert
ing,我想您确实知道开始的数组维度。
template<class T>
void Matrix<T>::set(const int i, const int j, const T v) {
try {
m[i][j] = v;
} catch (std::exception& e) {
std::cout << "Standard exception: " << e.what() << std::endl;
}
}
你没有提到 m
是什么类型,但假设它是在 operator[]
中进行边界检查的自定义类型,那么你应该没问题。边界检查将(或应该)发生,并且应该抛出异常,在任何越界写入尝试之前。
但请注意,C++ 不会对原始 (C) 数组进行自身边界检查,在其 operator[]
实现中也不会进行任何标准库类型,因此如果 m
是一个这些类型,那么你将永远不会抛出异常。相反,STL 类型提供了一个 at()
方法,如果需要进行边界检查,您应该使用该方法。
这是我的代码:
template<class T>
void Matrix<T>::set(const int i, const int j, const T v) {
try {
m[i][j] = v;
} catch (std::exception& e) {
std::cout << "Standard exception: " << e.what() << std::endl;
}
}
可是,我这里安全吗?我的意思是,有可能 i
and/or j
超出了范围,但是程序接收到分段错误,然后会抛出异常吗?
如果这不是一个好方法,那么我应该使用 assert()
吗?
只需添加边界检查。
C++ 不对数组进行边界检查,更不用说抛出异常了。
使用 vectors/std::array,您可以使用 .at()
方法而不是 []
运算符来进行检查。
最后,GSL 引入了 array_view
,它允许您添加 "zero cost annotation",以便分析工具可以进行边界检查。目前还没有出现 GSL 的实际标准实现。另见:
没有
仅从数组读取时,异常检查可能还可以(但一点也不优雅)。
然而,在写入时,您可能会覆盖 "foreign" 内存,这是一个巨大的安全风险,而且它可能会通过覆盖堆栈帧来改变执行流程,谁知道呢 - 也就是说,肯定存在某些情况当异常处理程序不会 运行 时,即使它实际上应该抛出。
最好的决定是在每次迭代时检查索引。
鉴于您提到了 assert
ing,我想您确实知道开始的数组维度。
template<class T>
void Matrix<T>::set(const int i, const int j, const T v) {
try {
m[i][j] = v;
} catch (std::exception& e) {
std::cout << "Standard exception: " << e.what() << std::endl;
}
}
你没有提到 m
是什么类型,但假设它是在 operator[]
中进行边界检查的自定义类型,那么你应该没问题。边界检查将(或应该)发生,并且应该抛出异常,在任何越界写入尝试之前。
但请注意,C++ 不会对原始 (C) 数组进行自身边界检查,在其 operator[]
实现中也不会进行任何标准库类型,因此如果 m
是一个这些类型,那么你将永远不会抛出异常。相反,STL 类型提供了一个 at()
方法,如果需要进行边界检查,您应该使用该方法。