2011-09-12 4 views
0

これは、C++演算子のオーバーロードを調べるためにコーディングした素朴な例です。私がそれを実行すると、コードは文c = a + bでハングします。コントロールが決して届かないc.display();なぜこのコードが上記の場所でハングしますか?

cout << ptr << '\n';を代入演算子のオーバーロードされた関数に置くと、デバッグの一部として、HelloWorldが出力されるため、stringは不正な形式ではないようです。

なぜそれがハングするのですか?私は何が欠けているのですか?

class mystring 
{ 
    char *ptr; 

    public: 

    mystring(char *str = "") 
    { 
     ptr = new char[strlen(str) + 1]; 
     strcpy(ptr,str); 

    } 

    mystring operator +(mystring s) 
    { 
     char *str = new char[strlen(ptr) + strlen(s.ptr) + 1];//where should this memory be freed 
     strcpy(str,ptr); 
     strcat(str,s.ptr); 
     return mystring(str); 
    } 

    void operator =(mystring s) 
    { 
     strcpy(ptr,s.ptr); 

     //cout << ptr << '\n'; \\Debug - this prints out HelloWorld but still hangs 
    } 

    void display() 
    { 
     cout << ptr << '\n'; 
    } 

    ~mystring() 
    { 
     delete [] ptr; 
    } 
}; 

int main() 
{ 
    mystring a="Hello",b="World",c; 

    c = a + b; 

    c.display(); 

    getchar(); 

} 

EDIT:コンパイラ:MS-のVisual C++ 2010 Expressの/ Windowsの。

+0

'演算子= 'はメモリを割り当てません。 'operator +'は2回の割り当てを行います。 –

+0

また、適切なコピーコンストラクタを実装する必要があることを追加したいと思います。 – Nim

+0

valgrindなどのメモリプロファイラは、この種のメモリエラーを検出したでしょう。 – Francois

答えて

1

あなたが得ているのはメモリエラーだと思います。このライン:

c = a + b; 

次ん:

c.constructor() 
c.operator=(a.operator+(b)); 

とあなたのオペレータ=必要なものメモリ

void operator =(mystring s) 
{ 
    // ptr is allocated enough memory for "", i.e. one byte 
    strcpy(ptr,s.ptr); // copying more than one byte into one byte array 
    //cout << ptr << '\n'; // this works, but you've trashed memory with the strcpy 
} // stack might be corrupted here, depends where this is, so execution can end up anywhere 

の割り当てに失敗したのである:

void operator = (mystring &s) // reference! 
{ 
    delete [] ptr; 
    ptr = new char [strlen (s.ptr + 1)]; 
    strcpy (ptr, s.ptr); 
} 
+1

または、 'tempPtr = new char [strlen(s.ptr + 1)]; strcpy(tempPtr、s.ptr); swap(ptr、tempPtr); delete tempPtr;を実行して[強力な例外保証]を提供します(http://en.wikipedia.org/wiki/Exception_guarantees)。 –

+0

@Skizz - ありがとう。それは、デストラクタ関数内のdelete ptrをコメントアウトする場合にのみ機能します。どんな考えがあってもこれは起こりうる。それはptrがoperator =()ですでに解放/削除されているためですか?その後、修正は何ですか? – goldenmean

+0

@ goldenmean:おそらく、文字列をコピーするのではなく、 'ptr'の値がコピーされているからでしょう。あなたの 'operator +'は結果を値で返し、コピーと削除をしているので、 'ptr'は2回削除されます。 'operator ='と同じことをする 'mystring(const mystring&source)'コンストラクトを追加してみてください。また、 'ptr'を' 0'にセットすると、それを削除しても問題が起こらないようにする必要があります。 – Skizz

1

operator=が壊れています。 strcpyを実行する前に十分な(または任意の)メモリを適切に割り当てていません。これは未定義の動作につながります。

1

のchar * STR =新しいCHAR [STRLEN(PTR)+ STRLEN(s.ptr)+ 1]; //このメモリは、デストラクタで解放

メモリを解放する必要がある場合。

オペレータに=あなたが割り当てられたメモリを解放し、再び

+1

実際には強調表示されているその特定の行は 'operator +'にあるため、その関数でクリーンアップする必要があります。 2点目は正しいですが... – Nim

+0

申し訳ありませんが、私のせいです。もちろん、メソッドでメモリを解放する必要があります。 – Ilmirus

0

オペレータがそれを割り当てる必要があります=古いバッファを解放し、あなたは、コンストラクタで行うようにして新しいものを割り当てる必要があります。

0

コードには、c.display()を打つ前にブロックするような明白な問題はないようですが、のように見えます。のようになります。

操作cout << ptr << '\n';はストリームをフラッシュしません。これは、出力が後でキャッシュされる可能性があることを意味します。プログラム全体でが基本的にで完了し、ユーザーがgetchar()に文字を入力するのを待っている場合があります。

デバッガでコードを実行するか、出力をcout << ptr << endl;に変更してみてください。

ところで、あなたはoperator+にメモリをリークしているので、おそらくそれを処理する必要があります。私はあなたがすでにそれを行う方法について尋ねたことを知っています、あなたは提案された解決策を好まなかった(または理解した)かもしれないが、それをそのまま残すことは解決策ではないかもしれません。

operator=は、完全な文字列を保持するのに十分な領域がないことを保証していません。つまり、未定義の動作を引き起こす可能性があります。

関連する問題