2017-03-21 24 views
0

C++のコードサンプルでは、​​アクセス違反やヒープの破損によってランダムにアプリケーションが失敗する理由を説明できません。私は、サンプルに現在悩んでいるコードが含まれていることを知っています(charへのポインタで直接作業しています)が、これは単なる学習目的のためのものです。誰かがコードを見て、私が見逃していることが分かったら教えてもらえれば、とても感謝しています。ありがとう。新しいチャンクでのアクセス違反/ヒープの破損

class Operand 
{ 
private: 
    double value; 
    char* message; 
public: 
    Operand(double value); 
    ~Operand(); 
    char* operator+(const Operand& other); 
}; 

Operand::Operand(double value) 
{ 
    this->value = value; 
} 

char* Operand::operator+(const Operand& other) 
{ 
    char s[256]; 
    double sum = this->value + other.value; 
    sprintf_s(s, "The sum of %f and %f is %f", this->value, other.value, sum); 
    this->message = new char[strlen(s)]; //this is where it sometimes crashes with an access violation 
    strcpy_s(this->message, sizeof(s), s); 
    return this->message; 
} 

Operand::~Operand() 
{ 
    if (this->message != nullptr) 
     delete[] this->message; 
} 

int main() 
{ 
    double operand1, operand2; 
    cout << "Please input the calculator parameters: operand1 operand2: "; 
    cin >> operand1 >> operand2; 

    auto Operand1 = Operand(operand1); 
    auto Operand2 = Operand(operand2); 
    char* message1 = Operand1 + Operand2; 
    char* message2 = Operand2 + Operand1; 
    cout << message1 << "\n"; 
    cout << message2 << "\n"; 

    return 0; //and sometimes it crashes right after outputting to cout 
} 

2つのchar *メッセージポインタが異なるオペランドインスタンスに属しているため、2つのchar *メッセージポインタが互いに干渉する理由はわかりません。それが本当にそれの原因であれば。それとも、私は何かを逃しています。

アイデアが足りないので、私は目の第二のペアを本当に感謝します。ありがとう。

答えて

4

メモリ破損の原因となるバグは複数あります。

その他の回答では、メモリ割り当てが不十分であることが既に説明されています。しかし、それはあなたの問題の中では最小です。

初期化されていないポインタ

Operandのコンストラクタはmessageメンバーの初期化に失敗しました。デストラクタは、決して新しくされなかったポインタをdeleteに試みます。 3/5違反

示すクラスviolates the Rule Of The Three

ルール。少なくとも、適切なコピーコンストラクタと代入演算子も必要です。

operator+リークメモリ

が既に割り当てられた場合、これは、messagedelete既存のコンテンツに故障によるメモリリークをもたらすであろう。

これらはすべて、コードの大まかなレビューの後すぐに判明したバグです。多分もっとカップルがあります。

+0

良いフィードバックをいただきありがとうございます。私のサンプルでは複数のベストプラクティスが壊れているかもしれませんが、主に学習目的のためです。これは完全に設計されたものではありません。しかし、本当にありがとうございます。 –

+0

初期化されていないポインタについて、nullptrに初期化すると、問題がなくなります。私は既にnullptrをチェックしていますので、削除する前に –

+0

はい、その特定の問題に対処します。 –

3

あなたは終端のヌルのための余分なバイトを割り当てる必要があります。operator+

this->message = new char[strlen(s) + 1]; 
+0

ありがとう、私はそれを逃した。そして、割り当ての直後に別の問題もあったようです。 strcpy_s呼び出しで、私は間違ったsizeinbytesを指定していました。 strlen(s)+1を指定すると、メモリ違反がなくなった –

1

は、あなたがnew char[strlen(s)]と新しい文字列のための場所を作成しています。それは短い1文字です。あなたは最終的に'\0'のためのスペースが必要です。

その後、文字列をコピーすると、'\0'はメモリ内の次のバイトを上書きします。これは未定義の動作につながります。

+0

@ M.M、それは私が言ったことです...愚かなiPadは聞いていません...ありがとう。 – Aganju

関連する問題