-4

これは私にはかなり奇妙なバグのようです。私の C++ プログラムは segfault になっており、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 を使用してコンストラクターの最初の行にブレークポイントを設定します。次の 2 行を実行した後、b.floors[1] の値が変更され、呼び出し時に segfault が発生します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

何が起こっているのか誰にも分かりませんか?

4

1 に答える 1

2

コードの問題は、初期化されていないポインター ( 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実装の詳細によっては、指定されたオブジェクトをコピーすることもできます。

于 2012-09-26T03:07:48.527 に答える