3

準データベースをプログラミングしています。

私はクラスのペアを持っています:

class Pair{
    MyString m_key;
    Data* m_data;
}

次に、メソッド AddItem がペアを作成し、データベースに追加します。

Data Ivanov(1, 10, "Manager", 100000);
Data Petrov(2, 20, "Manager", 200000);
MyString* employee0 = new MyString("Ivanov");
MyString* employee1 = new MyString("Petrov");
bd.AddItem(employee0, &Ivanov);
bd.AddItem(employee1, &Petrov);

データベース自体が要素の数と容量を監視します。class Bd{ プライベート: int m_size; int m_capacity; ペア** ar; ... }

アイテムを追加すると、容量がオーバーフローするとデータベースが伸びます。アイテムを削除すると、将来使用される可能性のある空のセルが発生します。これは、ヒープを断片化しすぎないようにするために行われます。

void Bd:: AddItem(MyString* key, Data* data){
    if (m_size < m_capacity){
        *ar[m_size+1] = Pair(key, data);
    }
    else{ 
        if (m_size == 0){
            ar = new Pair*[++m_size];
            m_capacity++;           
            ar[0] = new Pair(key, data);
            stop
        }
        else{
            Pair** tmp = new Pair*[++m_size];  
            m_capacity++;
            memcpy(tmp, ar, m_size * sizeof(Pair*));
            delete[] ar;
            ar = tmp;
            ar[m_size-1] = new Pair(key, data);
            stop
        }
    }
}


void Bd::RemoveItem(const char* a_key){
    Pair** tmp_ar = this->get_ar();
    for (int i = 0; i < m_size; i++){       
        Pair* tmp_key = tmp_ar[i];
        MyString* tmp_my_string= (*tmp_key).get_m_key();
        const char* tmp_str = (*tmp_my_string).GetString();
        if ( strcmp(tmp_str, a_key) == 0){
            delete ar[i];           
            for (int j = i; j < m_size-1; j++){
                *ar[j] = *ar[j+1];
            }
            delete ar[m_size-1];
            m_size--;
            break;
        }
        stop
        if (i == (m_size-1)){
            cout << "No such person." <<endl;           
        }
    }   
    stop
}

さて、BDを使いたいと思います。

cout << bd;
bd.Print("Ivanov");
bd.Print("Petrov");

それは完全に機能します。データベース全体または任意の要素も出力します。

次に、イワノフ氏を削除します。bd.RemoveItem("イワノフ");

今、私はこれのいずれかに問題があります:

bd.Print("Petrov");
cout << bd;

クラス Data に印刷メソッドがあります。

void Data:: print_info(){   
    cout << "Sex: " << this->getSex() << ", age: " << age <<", position: " << position <<", salary: ";
    cout << salary << endl; 
}

これは私が問題を抱えている場所であるため、特別に2回目のカウントを作成しました。給与は、スコープにはっきりと表示されますが、全体の問題を引き起こします。この写真を見てください:

ここに画像の説明を入力

もう 1 ステップ実行すると、ヒープの破損に関するエラーが表示されます。出力ウィンドウに次のように表示されます。 HEAP: Free Heap block 296b30 modified at 296b58 after it was freed

この給与を印刷できない理由を理解するのを手伝ってくれませんか?

4

1 に答える 1

0

に次の問題がありAddItem()ます。

void Bd:: AddItem(MyString* key, Data* data){
    if (m_size < m_capacity){
        *ar[m_size+1] = Pair(key, data);
    }

m_size未満の場合、m_capacity新しいアイテムを追加しますが、増加しませんm_size

    else{ 
        if (m_size == 0){
            ar = new Pair*[++m_size];
            m_capacity++;           
            ar[0] = new Pair(key, data);
            stop
        }

m_capacity0であることを確認するつもりだったと思います。

        else{
            Pair** tmp = new Pair*[++m_size];  
            m_capacity++;
            memcpy(tmp, ar, m_size * sizeof(Pair*));
            delete[] ar;
            ar = tmp;
            ar[m_size-1] = new Pair(key, data);
            stop
        }

memcpyからコピーしarていm_sizeます。インクリメントする前は のサイズでしm_sizeたが、現在は のサイズになっているm_size-1ため、配列の末尾を超えてコピーしました。

そして、次の問題RemoveItem():

if ( strcmp(tmp_str, a_key) == 0){
    delete ar[i];           
    for (int j = i; j < m_size-1; j++){
        *ar[j] = *ar[j+1];
    }
    delete ar[m_size-1];
    m_size--;
    break;
}

delete ar[m_size-1]に移動したばかりのアイテムを削除しようとしていますar[m_size-2]。これを削除したくありません。

この削除が問題の一部である可能性があると思います。具体的には、次の 2 つの変更が役立つと思います。

  1. コメントに記載されているように*ar[j] = *ar[j+1]行を変更します。ar[j] = ar[j+1]
  2. 行を取り除きdelete ar[m_size-1];ます。行の変更と同様に、これはar絶対に必要ありません。

これですべての問題が解決するわけではありませんが、彼のメソッドPetrovを呼び出す前に、削除していないことを確認できます。print_info()

于 2013-04-16T19:17:10.423 に答える