如题。当dump定位到这个地方时,有理由怀疑是下标访问string时越界了。
我们先看Checked Iterators中的例子。
-
- #define _SECURE_SCL 1
- #define _SECURE_SCL_THROWS 1
- #include <vector>
- #include <iostream>
- using namespace std;
- int main() {
- vector v;
- v.push_back(67);
- int i = v[0];
- cout << i << endl;
-
- try {
- i = v[1];
- }
- catch (std::out_of_range) {
- cout << "invalid container access" << endl;
- }
- };
这里vector访问越界,catch会抓到异常。但是如果把vector换成string:
- #include <string>
- int main() {
- string str = "";
- char s;
- try {
- s = str[1];
- }
- catch (std::out_of_range) {
- cout << "invalid container access" << endl;
- }
- };
却什么也catch不到,Release版直接crash。通过dump定位到如题的错误。为什么呢?
看一下string::operator[]()的实现。它在Microsoft Visual Studio 9.0/VC/crt/src/xstring中:
- reference __CLR_OR_THIS_CALL operator[](size_type _Off)
- {
- #if _HAS_ITERATOR_DEBUGGING
-
- if (this->_Myfirstiter != _IGNORE_MYITERLIST)
- {
- if (_Mysize < _Off)
- {
- _DEBUG_ERROR("string subscript out of range");
- _SCL_SECURE_OUT_OF_RANGE;
- }
- }
- #else
- _SCL_SECURE_VALIDATE_RANGE(_Off <= _Mysize);
- #endif /* _HAS_ITERATOR_DEBUGGING */
- return (_Myptr()[_Off]);
- }
而_SCL_SECURE_VALIDATE_RANGE是在/VC/include/yvals.h中定义的:
- #define _SCL_SECURE_VALIDATE_RANGE(cond) /
- { /
- if (!(cond)) /
- { /
- _ASSERTE((#cond, 0)); /
- _SCL_SECURE_OUT_OF_RANGE_NO_ASSERT; /
- } /
- __analysis_assume(cond); /
- }
只要能走到红色位置,就可以和vector一样抛出out_of_range异常,可惜却没有。经跟踪,发现是_SECURE_SCL_THROWS宏在搞鬼。
- #if _SECURE_SCL_THROWS
- #define _SCL_SECURE_INVALID_ARGUMENT_NO_ASSERT _Xinvarg()
- #define _SCL_SECURE_OUT_OF_RANGE_NO_ASSERT _Xran()
- #else /* _SECURE_SCL_THROWS */
- #define _SCL_SECURE_INVALID_ARGUMENT_NO_ASSERT _SCL_SECURE_INVALID_PARAMETER("invalid argument")
- #define _SCL_SECURE_OUT_OF_RANGE_NO_ASSERT _SCL_SECURE_INVALID_PARAMETER("out of range")
可是我明明 #define _SECURE_SCL_THROWS 1 了啊。过一段时间有机会再查吧。