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