如何检测通过错误大小的空c数组

How To detect an empty C-array passed with wrong size?

本文关键字:数组 错误 过错 何检测 检测      更新时间:2023-10-16

我有一个binarysearch函数,接口如下:

bool binarysearch(int* array, int size, int findnum) {
    doBinarySearch(array, 0, (size-1), findnum);
}  

doBinarySearch的代码是:

bool doBinarySearch(int* array, int start, int end, int findnum) {  
    if (end <= start)
        return false;
   int mid = (start+end)/2;
   if (array[mid] == findnum) {
       return true;
   } else if (findnum < array[mid]) {
       return doBinarySearch(array, start, mid, findnum);
   } else {
       return doBinarySearch(array, mid+1, end, findnum);
   }
}
我写了一个单元测试来测试上面的函数。如果我调用binarysearch与空数组和错误的大小从main,代码段。意料之中的故障。例如
int main() {  
    int *array;  
    binarysearch(array, 10, -1);    
}

但是如果我写一个单元测试类,并有一个函数来完成上面的工作,那么二进制搜索就不会崩溃。知道为什么会有不同的行为吗?

class TestBinarySearch {
    public:
        void testEmptyArray() {
            int *array;
            binarysearch(array, 10, -1);
        }
 };
 int main() {
     TestBinarySearch testObj;
     // below line does not cause seg fault. and -1 is found for some reason
     testObj.testEmptyArray(); 
 }

另一个问题-是否有任何方法来检测seg。如果有人调用了错误大小的函数?我看到一些使用信号捕获的例子,但在那之后,除了退出程序,还能做什么?

两种写法都会调用未定义行为。未定义行为可以是任何。它坠落在一个你应该感激的地方;不幸的是,它在另一方面"成功"了,但这是很有可能的。下次重启电脑或运行程序时,这种行为甚至可能会改变,谁知道呢。这是未定义的。

如果你用的是Linux,在valgrind下运行这两个程序,看看它说什么。即使没有崩溃,它也可能报告错误。

读取超出数组末尾是未定义的行为,正如John所说。编译器可以做任何它喜欢的事;你的软件可能会崩溃,可能会处理垃圾数据,可能会重新格式化你的硬盘(至少在标准一致性方面)。

没有办法检测给定的数组大小是否错误。

解决这个问题的正确方法是传入一个STL容器而不是一个C数组。至少,您可以这样重写binarySearch函数:

bool binarysearch(std::vector<int> array, int findnum) {
    doBinarySearch(&array[0], 0, array.size()-1, findnum);
}

这种情况不是一个空数组,这是一个单化的指针变量。对未初始化指针的解引用是未定义行为。这是一个程序错误,你不能防止它。

未定义行为意味着任何事情都可能发生。崩溃一次,别再崩溃了,一切都在意料之中。

有了这个API,你的调用者和你的单元测试必须确保传入的数组是有效的,并且至少与传入的长度一样长,并且绝对没有办法通过编程检查这是如此

你可以考虑将API改为使用STL集合,但那将是另一个问题。

顺便说一句,你有一个不相关的错误。代码应该是:

if (end < start) return false;