0

出于某种原因,以下程序在打印“我到达这里”之前崩溃。当我注释掉 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

我不知道为什么会这样。任何帮助将不胜感激!

4

3 回答 3

7

它崩溃了,因为您在分配 c 时只分配了一个 double ,然后通过访问第一个之后的元素继续超出边界。在这种情况下,似乎在处理异常之后进行了一些清理,并且 glibc 检测到损坏的内存。

问题线如下:

double* c = new double(*b);

for (int i = 0; i < 6; i++) {
        c[i] = i+1;
}

它分配一个新的 double 来复制 *b 的值(或者 b[0] 如果你喜欢),因为 b 只是一个指针,所以取消引用它不会调用复制数组的复制构造函数。

您最好使用 std::vector ,因为它会自动为您处理任何内存分配和释放以及异常安全。如果你error_function抛出了一个你没有处理的异常,它仍然会正确清理,而你new的内存不会像现在这样。

从技术上讲,这是未定义的行为,所以任何事情都可能发生。

于 2012-08-17T20:51:13.313 回答
1

你的问题在这里:

double* c = new double(*b);

这是为一个 double 分配空间并给它一个初始值b[0]。稍后您将分配给c[1]等。这是未定义的行为。

于 2012-08-17T20:53:43.180 回答
1

添加到timans答案。

您的程序正在发生堆溢出。

for (int i = 0; i < 6; i++) {
    c[i] = i+1;
}

double c[0] 的地址为 new 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[]。

于 2012-08-17T21:02:30.377 回答