1

問題は代入演算子にあります。文字列クラスのポインタのメモリの割り当てを解除して再割り当てするのを忘れてしまいました。誤ってコピーコンストラクタのように扱ったに違いありません。これは、メモリ管理が非常に重要である理由の素晴らしい教訓です。皆さんの助けに感謝します。

iveは私自身の文字列クラスを実装しました、そしてこれはそれが壊れる前の呼び出しスタックの最後の関数のようです。

String::~String(){
    delete [] rep;
    len=0;
}

誰かが私に問題が何であるかを理解するのを手伝ってもらえますか?

これがそれを呼び出す関数です

template <class T> 
void SList<T>::RemoveAfter(typename SList<T>::Iterator i){        
    assert(i.nodePointer !=0 && i.nodePointer->next!=0);
    Node *save = i.nodePointer -> next;
    i.nodePointer->next = i.nodePointer->next->next;
    delete save;

}

これが発生する理由を理解するために必要な情報が他にある場合は、お知らせください。

ちなみに、int型を使用する場合、この問題は発生しないので、問題は文字列クラスにあるはずです...そうですか?

要求に応じて詳細情報:

struct Node{ // Node: Stores the next Node and the data.
    T data;
    Node *next;
    Node() {next =0;}
    Node(const T& a, Node *p = 0){data=a;next=p;}

};

エラー:

WindowsがAlgorithms.exeでブレークポイントをトリガーしました。これは、ヒープの破損が原因である可能性があります。これは、Algorithms.exeまたはロードされたDLLのバグを示しています。これは、Algorithms.exeにフォーカスがあるときにユーザーがF12キーを押したことが原因である可能性もあります。出力ウィンドウには、より多くの診断情報が表示される場合があります。

壊れた機能の例:

    String item1("Example"), item2("Example");
    SList<String> list1;        
    list1.AddFirst(item2);
    list1.AddFirst(item1);
    list1.AddLast("List Class");
    list1.AddLast("Functionality");

    SList<String>::Iterator i1;

    i1 = list1.Begin();     
    i1++;
    i1++;
    list1.RemoveAfter(i1);

動作する例

    SList<int> list1;       
    list1.AddFirst(1);
    list1.AddFirst(2);
    list1.AddLast(3);
    list1.AddLast(4);

    SList<int>::Iterator i1;

    i1 = list1.Begin();     
    i1++;
    i1++;
    list1.RemoveAfter(i1);


    system("pause");

詳しくは:

//Default Constructor
String::String(){
rep = new char[1];
rep[0] = '\0';
len = 0;
}  

//Constructor - Converts char* to String object
String::String(const char *s){
len=0;
const char *temp = s;
while(*temp){
    ++len;
    ++temp;
}//Sets len of rep to the length of s
rep = new char[len + 1];
for(int i=0; i<=len; ++i)
    rep[i]=s[i];
}

//Copy Constructor
String::String(const String &obj){
len=0;
char *temp = obj.rep;

while (*temp){
    ++len;
    ++temp;
}//Sets len of rep to length of obj.rep
rep = new char[len + 1];
for (int i = 0; i<=len; ++i)
    rep[i] = obj.rep[i];
}

//Assignment operator
const String& String::operator=(const String &rhs){
if (this != &rhs){
    len=0;
    char *temp = rhs.rep;
    while(*temp){
        ++len;
        ++temp;
    }//Sets len of this to length of rhs.rep
    for(int i = 0; i<=len;++i)
        rep[i]=rhs.rep[i];
}
return *this;
}
4

1 に答える 1

2

代入演算子では、が指す割り当てられた領域の境界外に書き込んでいる可能性がありますchar* rep。これにより、スタックが破損する可能性があります(つまり、undefined-behaviorが発生します)。

後でメモリのこのセグメントの割り当てを解除しようとすると、スタックが破損すると問題が発生する可能性があります。これが、アプリケーションの実行時に表示されるエラーメッセージの理由である可能性が非常に高くなります。

メッセージ自体で述べられているように、「これはヒープの破損が原因である可能性があります」


問題を解決するにはどうすればよいですか?

代入演算子の内部では、次の3つのことを行う必要があります。

  1. これで以前に割り当てられたメモリの割り当てを解除します this- > lenrhs.lenの値が同じでない場合は、手順2もスキップします) 。
  2. rhsrhs.repに持っているのと同じ量のメモリを割り当てます(つまり、 rhs.lenバイト)
  3. this-> lenを更新して、新しいコンテンツの長さを表します
  4. rhs.repが指すメモリに格納されているバイトを、 this->repが指すメモリセグメントにコピーします。

現在、ステップ3と4のみを実行しています。

于 2012-07-15T22:07:39.940 に答える