【问题标题】:Initializing an integer member variable results in changing another member variable's address初始化整数成员变量会导致更改另一个成员变量的地址
【发布时间】:2012-09-26 02:45:46
【问题描述】:

这对我来说似乎是一个相当奇怪的错误。我的 C++ 程序出现段错误,我发现使用 GDB 时有些奇怪。我有以下构造函数和复制构造函数:

Bank::Bank(char mode, int floor_dimensions_, int num_floors_) : floor_dimensions(floor_dimensions_), num_floors(num_floors_) {
    for (int i = 0; i < num_floors; i++) {
        floors[i] = new Floor(floor_dimensions);
    }

    if (mode == 'M') {
        read_map(floors);
    } else if (mode == 'C') {
        read_coords(floors);
    }
}

Bank::Bank(const Bank& b) {
    floor_dimensions = b.floor_dimensions;
    num_floors = b.num_floors;

    cout << floor_dimensions << endl;
    cout << num_floors << endl;

    for (int i = 0; i < num_floors; i++) {
        floors[i] = new Floor(*b.floors[i]);
        floors[i]->print_map();
}

这个类的定义是这样的

class Bank {
    /** The number of floors the bank has */
    int num_floors;

    /** The dimension of each of the floors */
    int floor_dimensions;

    /** The floors in the bank */
    Floor* floors[];

private:
    Bank(char mode, int floor_dimensions_, int num_floors_);
    Bank(const Bank& bank);
    ~Bank();
    void read_map(Floor** floor);
void read_coords(Floor** floor);
}

现在我使用 GDB 在构造函数的第一行设置断点。执行完后面两行,b.floors[1]的值发生了变化,导致我调用b.floors[i]-&gt;foo()时出现segfault。

    Breakpoint 1, Bank::Bank (this=0x7fffffffe050, b=...) at bank.cpp:29
29      floor_dimensions = b.floor_dimensions;
(gdb) p b.floors[0]
$4 = (Floor *) 0x610070
(gdb) p b.floors[1]
$5 = (Floor *) 0x6103f0
(gdb) p b.floors[2]
$6 = (Floor *) 0x610770
(gdb) n
30      num_floors = b.num_floors;
(gdb) p b.floors[0]
$7 = (Floor *) 0x610070
(gdb) p b.floors[1]
$8 = (Floor *) 0x8006103f0
(gdb) p b.floors[2]
$9 = (Floor *) 0x610770
(gdb) n
32      cout << floor_dimensions << endl;
(gdb) p b.floors[0]
$10 = (Floor *) 0x610070
(gdb) p b.floors[1]
$11 = (Floor *) 0x800000003
(gdb) p b.floors[2]
$12 = (Floor *) 0x610770

有人知道发生了什么吗?

【问题讨论】:

  • Floor* floors[]; 是无效的语法。此外,您没有复制数组,因此您可能在每次销毁对象时释放相同的指针。
  • @SethCarnegie 那么我将如何创建一个指针数组呢?而且我也没有故意放代码来复制数组。
  • 为什么省略了数组复制代码?这是最可能的错误来源!
  • 另外——为什么要在源代码上调用 foo()——因为类 decl 中缺少这个
  • @AdrianCornish 我在哪里修改它? AndrewShepherd 代码按照我提供的方式崩溃,其中 foo 是任何函数(甚至是空函数)。

标签: c++ pointers gdb segmentation-fault


【解决方案1】:

您的代码的问题很可能是您试图访问未初始化的指针 (b.floors)。假设b 是这个复制构造函数的结果,那么b.floors 将指向随机内存。然后b.floors[i] 将比b.floors 指向的内存提前一些字节指向随机内存,最终您使用-&gt; 取消引用这个随机地址,这会导致分段错误。

解决你的问题的方法是正确分配和复制楼层数组:

floors = new Floor* [num_floors];
for (int i=0; i<num_floors; ++i)
  floors[i] = b.floors[i];

您可能还想复制指向对象Floor,具体取决于您的实现细节。

【讨论】:

  • 谢谢。我通过循环调用 new floor() 来初始化楼层,而没有先做floors = new Floor*[num_floors]; 另外,你给我的代码floors = new (Floor*) [num_floors]; 给出了编译错误bank.cpp:36:23: error: array bound forbidden after parenthesized type-id bank.cpp:36:23: note: try removing the parentheses around the type-id
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 2014-09-08
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多