#include <iostream>
#include <vector>
using namespace std;
void test_bad_alloc(unsigned char *start) {
try {
vector<int> v = vector<int>(start + 1, start - 13);
}catch (bad_alloc) {
std::cout<<"bad alloc"<<std::endl;
}
}
int main() {
unsigned char a[20] = {0};
test_bad_alloc(a);
return 0;
}
这段代码与我的真实项目类似,我发现它会导致bad_alloc异常,为什么?这个向量的构造函数是不明确的吗?
答案 0 :(得分:2)
您的程序在尝试评估start - 13
时会有未定义的行为。
start
指向a
数组的第一个元素,因此start - 13
会创建一个无效指针,因为它超出了数组的范围。你根本做不到,它也没有意义。你期望指针指向什么,确切地说?
请注意this is undefined behaviour,即使您没有取消引用指针。
在任何情况下,未定义的行为意味着您的程序可以执行任何操作,并且&#34;任何事情&#34;包括抛出随机异常。
事实上,我无法重现std::bad_alloc
例外。例如,最新的Clang会抛出std::length_error
而最新的Visual C ++会崩溃。它还取决于编译器标志。
在你的情况下可能发生的事情是编译器产生了二进制代码,它只是继续使用无效指针并将其传递给向量构造函数,然后向量构造函数尝试从中创建一个巨大的整数范围,但失败了。
也许你想要这样的东西呢?
void test_bad_alloc(unsigned char *start, unsigned char* end) {
try {
vector<int> v = vector<int>(start + 1, end - 13);
}catch (bad_alloc) {
std::cout<<"bad alloc"<<std::endl;
}
}
// ...
test_bad_alloc(a, a + 20);
我也无法帮助但是注意到矢量定义行中的Java主义。你可以而且应该这样写:
vector<int> v(start + 1, end - 13);
答案 1 :(得分:1)
问题在vector<int> v = vector<int>(start + 1, start - 13);
Range Constructor期望
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
即。第一个元素到最后一个元素但是,代替SecondIterator
,您使用的是start - 13
,它位于已分配数组的内存空间之外。
在最好的情况下,它可能也在您的进程的内存空间之外,并且可能导致分段错误,在最坏的情况下,它可能会获取垃圾值,使用错误数据覆盖文件或通过套接字发送错误消息。
答案 2 :(得分:0)
vector<int>(ptr1, ptr2)
调用的构造函数是具有两个迭代器的范围构造函数。它尝试为从ptr1开始并在ptr2之前结束的元素分配内存。但是,当您的ptr2小于ptr1时,您将分配负数元素。
由于ptr2=start-13
会在分配的数组之外引用,我猜你想要ptr2=start+13
。