出于某种原因,在“我到达这里”之前打印了以下程序崩溃。当我注释掉try-catch部分时,程序会正常运行并退出。
#include <iostream>
int error_function () {
throw 5;
return 0;
}
int main () {
double* b = new double[6];
for (int i = 0; i < 6; i++) {
b[i] = i;
}
double* c = new double(*b);
for (int i = 0; i < 6; i++) {
c[i] = i+1;
}
for (int i = 0; i < 6; i++) {
std::cout << b[i] << " " << c[i] << std::endl;
}
try {
error_function();
}
catch (int t) {
std::cout << "catched an int: " << t << std::endl;
}
std::cout << "i got here" << std::endl;
return 0;
}
这是程序崩溃时得到的整个输出:
0 1
1 2
2 3
3 4
4 5
5 6
catched an int: 5
*** glibc detected *** ./main: free(): invalid next size (fast): 0x0000000001f22070 ***
======= Backtrace: =========
/lib/libc.so.6(+0x77806)[0x7f2b273a0806]
/lib/libc.so.6(cfree+0x73)[0x7f2b273a70d3]
./main[0x400d92]
(a bunch of stuff)
Aborted
我不知道为什么会这样。任何帮助将不胜感激!
答案 0 :(得分:7)
它崩溃是因为你在分配c时只分配了一个double,然后通过访问第一个之后的元素继续超出边界。看起来在这种情况下,在处理异常之后会有一些清理并且glibc已经检测到损坏的内存。
问题在于:
double* c = new double(*b);
for (int i = 0; i < 6; i++) {
c[i] = i+1;
}
它分配一个复制* b(或b [0]的值)的新double,如果你喜欢的话,因为b只是一个指针,因此解除引用它不会调用复制数组的复制构造函数。
您最好使用std :: vector,因为它会自动为您处理任何内存分配和释放,以及异常安全。如果您的error_function
抛出了一个您没有处理的异常,它仍然可以正常清理,而您的new
内存不会如此。
从技术上讲,它是未定义的行为,所以任何事情都可能发生。
答案 1 :(得分:1)
你的问题在这里:
double* c = new double(*b);
这是为一个双精度分配空间并给它一个初始值b[0]
。稍后您将分配给c[1]
等。这是未定义的行为。
答案 2 :(得分:1)
添加到timans回答。
您的程序正在进行堆溢出。
for (int i = 0; i < 6; i++) {
c[i] = i+1;
}
double c [0]有一个新的double的地址和b [0]的值。但是c [1],c [2],....他们可能会覆盖与该程序相关的任何其他系统信息然后行为变得不确定。
更改此行,程序应该可以正常工作
double* c = new double[6];
for (int i = 0; i < 6; i++) {
c[i] = b[i]+1;
}
并且在从main返回之前不要忘记调用delete []。