在做剑指 Offer 04. 二维数组中的查找一题时,如下代码:
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
int i = matrix.size() - 1, j = 0;
while (i >= 0 && j <= matrix[0].size() - 1) {
if (matrix[i][j] > target) i--;
else if (matrix[i][j] < target) j++;
else return true;
}
return false;
}
};
在执行[[]],1
这个测试用例时,会出现如下错误:
Line 1033: Char 9: runtime error: reference binding to null pointer of type 'int' (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1043:9
根据网上查阅的资料得知是发生了数组越界,matrix[i][j]
当然会发生数组越界,越界在意料之中,疑惑的地方在于为什么程序仍然能够进入循环体导致越界?
while
的判断条件也很简单,两个变量都和vector
的size()
函数有关。
_NODISCARD size_type size() const noexcept { // return length of sequence
auto& _My_data = _Mypair._Myval2;
return static_cast<size_type>(_My_data._Mylast - _My_data._Myfirst);
}
在C++ reference中对
vector
中size_type
的介绍如下:an unsigned integral type that can represent any non-negative value of difference_type
size()
函数的返回值size_type
本质上是一个无符号整型,因此,在j <= matrix[0].size() - 1
中matrix[0].size() - 1
不是我们认为的结果-1
,而是将-1
的补码按照无符号整型转换成的一个很大的值(常识:计算机使用补码进行运算),因此,也就解释了为什么程序能够进入循环体导致数组越界了。
因此,需要对matrix[0].size()
做一下类型转换,下面的代码就可以成功通过测试用例了。
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
int i = matrix.size() - 1, j = 0;
while (i >= 0 && j <= (int)matrix[0].size() - 1) {
if (matrix[i][j] > target) i--;
else if (matrix[i][j] < target) j++;
else return true;
}
return false;
}
};
当然,如果提前对参数进行判空也就不会出现上述问题了,可见良好编程规范的重要性!
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
if (matrix.size() == 0 || matrix[0].size() == 0) {
return false;
}
int i = matrix.size() - 1, j = 0;
while (i >= 0 && j <= (int)matrix[0].size() - 1) {
if (matrix[i][j] > target) i--;
else if (matrix[i][j] < target) j++;
else return true;
}
return false;
}
};