如何检测传递错误大小的空C数组?

时间:2014-08-20 00:09:30

标签: c++ arrays unit-testing

我有一个带有接口的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调用错误的大小,则代码段。如预期的那样。 E.g。

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。如果有人调用错误大小的函数错误?我看到一些使用信号来捕获它的例子,但是除了退出程序之外,还可以做任何其他事情吗?

3 个答案:

答案 0 :(得分:2)

编写它的两种方式都会调用未定义的行为。未定义的行为可以是任何。它崩溃了,你应该感激;它成功了#34;在另一个是不幸但很可能。下次重新启动计算机或运行程序时,行为甚至可能会发生变化,谁知道。它未定义。

如果您使用的是Linux,请在valgrind下运行这两个程序并查看其内容。即使没有崩溃,它也可能会报告错误。

答案 1 :(得分:2)

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

无法检测到数组的大小是否正确。

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

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

答案 2 :(得分:2)

这种情况不是空数组,这是一个单位化指针变量。取消引用未初始化的指针是Undefined Behavior。这是一个程序错误,你无法防范它。

未定义的行为意味着可能发生任何事情。崩溃一次,而不是另一次,这一切都如预期的那样。

使用此API,您的调用者和您的单元测试必须确保传递的数组有效,并且至少只要传递长度,并且绝对无法以编程方式检查这是如此

您可以考虑更改API以使用STL集合,但这将是一个不同的问题。

你有一个不相关的错误吗?代码应该说:

if (end < start) return false;