初始化整数成员变量会导致更改另一个成员变量的地址

Initializing an integer member variable results in changing another member variable's address

本文关键字:成员 变量 另一个 地址 整数 初始化      更新时间:2023-10-16

这对我来说似乎是一个相当奇怪的错误。我的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]->foo() 时出现段错误。

    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

有人知道发生了什么吗?

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

问题的解决方案是正确分配和复制楼层阵列:

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

您可能还希望将指向的对象复制到Floor,具体取决于实现的详细信息。