1

私のコードをコンパイルしましたが、 "例外がスローされました:読み取りアクセス違反。 _Firstはnullptrでした。""未処理の例外がスローされました:読み取りアクセス違反_First was nullptr"というエラーは何を意味しますか?

これは私がまだC++の初心者であることを意味するものではありません。私はこのコードを数日間苦労しているので、この問題を理解するためにあなたの助けが本当に必要です。それはとてもイライラしています...

ありがとうございます。

#include <iostream> 
#include <cstring> 
#include <fstream> 
using namespace std; 

class MyString { 
public: 

    //default constructor 
    MyString(); 

    MyString(char* chars); 

    //copy constructor 
    MyString(const MyString &); 

    int length() const; 

    //destructor 
    ~MyString(); 

    //operator overloads 
    char& operator[](int index); 
    friend MyString operator+(const MyString& newWord, const MyString& newWord2); 
    MyString& operator+=(const MyString& newWord); 
    friend ostream& operator<<(ostream& newWord, const MyString& newWord2); 
    friend istream& operator >> (istream& newWord, MyString& newWord2); 
    friend bool operator==(const MyString& newWord, const MyString& newWord2); 
    friend bool operator!=(const MyString& newWord, const MyString& newWord2); 
    friend bool operator<(const MyString& newWord, const MyString& newWord2); 
    friend bool operator<=(const MyString& newWord, const MyString& newWord2); 
    friend bool operator>(const MyString& newWord, const MyString& newWord2); 
    friend bool operator>=(const MyString& newWord, const MyString& newWord2); 

private: 
    char* value; 
    int size; 
}; 

//default constructor 
MyString::MyString() { 

    value = NULL; 
    size = 0; 
} 

//copy constructor 
MyString::MyString(const MyString& newWord) { 

    //perform a deep copy to copy each of the value to a new memory 
    size = newWord.size; 
    char* newCopy = new char[size]; 

    for (int ii = 0; ii < size; ii++) { 
     newCopy[ii] = newWord.value[ii]; 
    } 
} 

//constructor with an argument 
MyString::MyString(char* chars) { 

    //give the value and the size 
    value = chars; 
    size = strlen(chars); 
} 

//find length 
int MyString::length() const { 

    return size; 
} 

//find the value of each index 
char& MyString::operator[](int index) { 

    return value[index]; 
} 

//operator + (concatenate) 
MyString operator+(const MyString& newWord, const MyString& newWord2) { 

    MyString concatenated; 
    concatenated = strcat(newWord.value, newWord.value); 
    return concatenated; 

} 

//operator += (append) 
MyString& MyString::operator+=(const MyString& newWord) { 

    char * newMemory = value; 
    value = new char[strlen(value) + newWord.length() + 1]; 
    strcpy(value, newMemory); 
    strcat(value, newWord.value); 
    if (size != 0) 
    { 
     delete[] newMemory; 
    } 
    size = strlen(value); 
    return *this; 
} 

//ostream operator 
ostream& operator<<(ostream& newWord, const MyString& newWord2) { 

    newWord << newWord2.value; 
    return newWord; 
} 


//istream operator 
istream& operator >> (istream& newWord, MyString& newWord2) { 

    const int MAX = 100; 
    char* ptr = new char[MAX]; 
    newWord >> ptr; 
    newWord2 = MyString(ptr); 
    delete ptr; 
    return newWord; 
} 

//all boolean operators 
bool operator==(const MyString& newWord, const MyString& newWord2) { 
    if (newWord.value == newWord2.value) { 
     return true; 
    } 
    else { 
     return false; 
    } 
} 

bool operator!=(const MyString& newWord, const MyString& newWord2) { 
    if (newWord.value != newWord2.value) { 
     return true; 
    } 
    else { 
     return false; 
    } 
} 

bool operator<(const MyString& newWord, const MyString& newWord2) { 
    if (newWord.value < newWord2.value) { 
     return true; 
    } 
    else { 
     return false; 
    } 
} 

bool operator<=(const MyString& newWord, const MyString& newWord2) { 
    if (newWord.value <= newWord2.value) { 
     return true; 
    } 
    else { 
     return false; 
    } 
} 

bool operator>(const MyString& newWord, const MyString& newWord2) { 
    if (newWord.value > newWord2.value) { 
     return true; 
    } 
    else { 
     return false; 
    } 
} 

bool operator>=(const MyString& newWord, const MyString& newWord2) { 
    if (newWord.value >= newWord2.value) { 
     return true; 
    } 
    else { 
     return false; 
    } 
} 

//destructor to release memory 
MyString::~MyString() { 
    delete[] value; 
} 

void test_copy_and_destructor(MyString S) { 
    cout << "test: copy constructor and destructor calls: " << endl; 
    MyString temp = S; 
    cout << "temp inside function test_copy_and_destructor: " << temp << endl; 
} 

int main() { 

    MyString st1("abc abc"); 
    MyString st2("9fgth"); 

    cout << "Copy constructor , << operator" << endl; 

    MyString st3(st1); 

    cout << "st3: " << st3 << endl; 

    test_copy_and_destructor(st2); 

    MyString st4; 

    cout << "operator + " << endl; 

    st4 = st3 + st2; 

    cout << "st4: " << st4 << endl; 

    cout << "st1 + st2: " << (st1 + st2) << endl; 

    cout << "operators [ ] " << endl; 

    for (int i = 0; i < st2.length(); i++) 
     cout << st2[i] << " "; 

    cout << endl; 

    cout << "operators += , ==, != " << endl; 

    st2 += st1; 

    if (st3 == st1) 
     cout << "st3 and st1 are identical " << endl; 
    else cout << "st3 and st1 are not identical " << endl; 

    if (st2 != st1) 
     cout << "st2 and st1 are not identical " << endl; 
    else cout << "st2 and st1 are identical " << endl; 

    cout << "operators < , <=, >, >= " << endl; 

    if (st2 < st1) 
     cout << "st2 < st1 " << endl; 
    else cout << "st2 is not less than st1 " << endl; 

    if (st1 <= st2) 
     cout << "st1 <= st2 " << endl; 
    else cout << "st1 is not less than or equal to st2 " << endl; 

    if (st1 > st2) 
     cout << "st1 > st2 " << endl; 
    else cout << "not (st1 > st2) " << endl; 

    if (st1 >= st2) 
     cout << "st1 >= st2 " << endl; 
    else cout << "not (st1 >= st2) " << endl; 

    cout << "operator >> " << endl; 

    //Open the data file 
    ifstream input("A9_input.txt"); 
    if (input.fail()) { 
     cout << "unable to open input file A9_input.txt, Exiting..... "; 
     system("pause"); 
     return 0; 
    } 
    MyString temp1; 
    MyString temp2("aaa"); 
    input >> temp1; 
    input >> temp2; 
    cout << "first element of input file: " << temp1 << endl; 
    cout << "second element of input file: " << temp2 << endl; 
    input.close(); 

    cout << "MyString says farewell....." << endl; 
    system("pause"); 
    return 0; 
} 
+0

エラーが表示されるまでにどのくらい離れていますか? –

+0

'value'が指す文字列で何かしようとしていますが、' value'は 'NULL'です。 – Barmar

+1

実行する前に歩いてみました。このコードは混乱しています。ヌルチェックもなく、 'operator +'は多数のバグがあります。strcatの最初の引数として 'const MyString'を使用するのでコンパイルしてはいけません。' strcat'は受信バッファが十分に大きくなければならない2番目の追加テキスト。 'operator + ='では 'newMemory'を使用して古いアドレスを保存しています...あなたの'演算子>> 'は奇妙です。あなたの比較演算子はポインタを比較し、あなたのデストラクタはあなたがポインタを所有していると仮定します。 MyString(char * s) 'を呼び出します。 – kfsone

答えて

1

あなたのコピーコンストラクタは、ターゲットのvalueを設定したことがないので、あなたは新しい文字列を使用しようとすると、valueが初期化されていません。ローカル変数newCopyを使用する代わりに、valueに割り当てる必要があります。

MyString::MyString(const MyString& newWord) { 

    //perform a deep copy to copy each of the value to a new memory 
    size = newWord.size; 
    value = new char[size]; 

    for (int ii = 0; ii < size; ii++) { 
     value[ii] = newWord.value[ii]; 
    } 
} 

また、char* charsを取るコンストラクタはcharsのコピーを作成する必要があります。それ以外の場合、パラメータがスコープ外になったローカル配列または削除された動的配列の場合、ポインタが無効になる可能性があります。また、デストラクタはdelete[] value;であるため、動的に割り当てられる必要があります。これは、文字列リテラルから初期化するときには正しくありません。

//constructor with an argument 
MyString::MyString(char* chars) { 

    size = strlen(chars); 
    value = new char[size]; 
    for (int i = 0; i < size; i++) { 
     value[i] = chars[i]; 
    } 
} 
+0

私はあなたが示唆したコードを実装しようとしたときに、まだこのエラーが発生します。ConsoleApplication5.exeの0x0F5E0E09(ucrtbased.dll)で例外がスローされました:0xC0000005:0x005D2000にアクセス違反を書き込みました。このアイデアはありますか?申し訳ありませんが、私はC++を2ヶ月使っています。あなたの大きな助けをありがとう! –

+0

申し訳ありませんが、そこにたくさんのコードがあります。あなたが持つ可能性のある問題をすべて見ることはできません。デバッガの使い方を学ぶ必要がありますので、プログラムの各ステップで変数を見て、いつ無効になるかを確認することができます。 – Barmar

0

アドレスに問題の全シリーズがあります:

まず、あなたはvalueは、0/NULL/nullptrことを可能にする(新しいC++ 11 nullptrキーワード最大限に活用!)。そうする場合は、すべての関数と演算子でこの可能性を考慮する必要があります。そうでなければ、無効なメモリ位置にアクセスしようとします(たとえば、strlen(value)を実行するとき)。まさにこれが例外の意味です(ほとんどの場合、0は有効なメモリアドレスではありませんが、埋め込みシステムにはいくつかの例外がありますが、そこに書き込むとシステム全体が壊れる可能性があります)。

すべての関数/演算子でこのような問題が発生しないようにするには、std :: stringと同様に、常にvalueをコンストラクタの既存の空の文字列に設定することをお勧めします(例外:std :: stringのすべての実装accept std::string(nullptr))。ユーザーには別の問題も回避しました。サイズ0の文字列に対して2つの異なる文字列表現を得ることができました:nullptr""

もう一つの問題は、あなたがはchar*をacceptyingコンストラクタの場合は、文字列ををコピーしていないが、デストラクタでそれを削除しているということです。問題:、

char buffer[64]; 
/* ... */ 
return MyString(buffer); 

すべての状況で(安全なのstd ::文字列–では不可能な何かを、多くの場合、既存の文字列の所有権を取るために効率的であるかもしれない:引数がスタック上に割り当てられた文字バッファー可能性があり上記のように、あるいは文字列リテラルreturn MyString("hello world");を割り当てても問題ありません(とにかく、リテラルはC++のchar const*ですが、多くのコンパイラでそれを取り除くことができます)あなたが所有権を奪うことを許可したいのであれば、私はデフォルトでそれをしません(文字列をコピーして)明示的に許可する別のコンストラクタを追加します(MyString(char*, bool takeOwnership = false)、(MyString(char const*)は常にコピー - constに注意してください)。もちろん、所有権があれば、どこかに覚えておく必要があります。所有権がある場合は、内部表現のみを削除します(デフォルト...)。

値は、==、!=、<、>、...演算子で比較しています。

char b1[] = {'a', 'b', 'c', 0 }; 
char b2[] = {'a', 'b', 'c', 0 }; 
bool isEqual = MyString(b1) == MyString(b2); 

isEqualfalse次のようになります。次の2つの異なる文字列は文字通り同じであれば、両方のvalueメンバーは、まったく同じ文字列を指しますが、ない場合にのみ、平等を得ることに注意してください!私はあなたがこれを意図していないと仮定します。むしろstd :: stringが提供するのと同じ動作です。もっと重大な問題は演算子です。<、< =、>、> =。両方のポインタが同じ配列を指しているか、または末尾のポインタ(b3 = b1 + 2)を指している場合にのみ、これらと比較することは合法です。そうでなければ、未定義の動作です。

私はあなたが持っているしたいと仮定行動を取得するには、strcmpを使用する必要があります。

あなたが適切なオペレータとXを置き換える
bool operator X(MyString const& l, MyString const& r) 
{ 
    return strcmp(l, r) X 0; 
} 

(、、あなたは!(l == r)として!=を定義することができ!(l > r)として<=の点に注意してください。等。)。

そして、してくださいしてくださいしてください:のようなものをしないでください。

if(a == b) 
    return true; 
else 
    return false; 

または

bool isWhatEver; 
if(c != d) 
    isWhatEver = true; 
else 
    isWhatEver = false; 

単に

return a == b; 

isWhatEver = c != d; 

補遺を書きます

rule of threeに違反しています。代入演算子を提供していません:operator=(MyString const& other)。 3つのルールは実際にはC++ 11でrule of fiveになりました。移動コンストラクタと移動代入演算子を追加することもできます。実装する前に、あなたのために非常に有用であるかもしれないhereを見て、持っている...


編集:

何が悪かったのか、単にアドレスから言うことはほとんど不可能です。あなたはスタックトレースを提供しておらず、あなたの固定コードではありませんでした。

私はあなたが意図したと思われるものにあなたのクラスを修正することができました。このバージョンはすべてのテストを実行しました。少なくとも、入力ファイルの内容は単に「こんにちは世界」でした。移動コンストラクタを省略します(ヒント:std :: swapを使用してください)。私はまだそれがバグフリーであることを保証しません...いくつかの助言:私のコードを取るだけでなく、何が間違っているかもしれないかを見るために私が別にしたことをよく見てください。最後の1つ:std :: vectorを使用してバッファサイズを超えているため、演算子>>失敗に対して安全です。

class MyString 
{ 
public: 

    //default constructor 
    MyString(); 

    MyString(char const* chars); 

    //copy constructor 
    MyString(const MyString &); 

    int length() const; 

    //destructor 
    ~MyString(); 

    //operator overloads 
    char& operator[](int index); 
    friend MyString operator+(const MyString& newWord, const MyString& newWord2); 
    MyString& operator+=(const MyString& newWord); 
    MyString& operator=(const MyString& newWord) 
    { 
     char* newValue = new char[newWord.size]; 
     delete value; 
     value = newValue; 
     size = newWord.size; 
     memcpy(value, newWord.value, size); 
     return *this; 
    } 
    MyString& operator=(char const* chars) 
    { 
     size_t newSize = strlen(chars); 
     char* newValue = new char[newSize]; 
     delete value; 
     value = newValue; 
     size = newSize; 
     memcpy(value, chars, size); 
     return *this; 
    } 
    friend ostream& operator<<(ostream& newWord, const MyString& newWord2); 
    friend istream& operator >>(istream& newWord, MyString& newWord2); 
    friend bool operator==(const MyString& newWord, const MyString& newWord2); 
    friend bool operator!=(const MyString& newWord, const MyString& newWord2); 
    friend bool operator<(const MyString& newWord, const MyString& newWord2); 
    friend bool operator<=(const MyString& newWord, const MyString& newWord2); 
    friend bool operator>(const MyString& newWord, const MyString& newWord2); 
    friend bool operator>=(const MyString& newWord, const MyString& newWord2); 

private: 
    char* value; 
    int size; 
}; 

//default constructor 
MyString::MyString() 
{ 
    value = new char[1]; 
    *value = 0; 
    size = 0; 
} 

//copy constructor 
MyString::MyString(const MyString& newWord) 
{ 
    //perform a deep copy to copy each of the value to a new memory 
    size = newWord.size; 
    value = new char[size]; 
    memcpy(value, newWord.value, size); 
} 

//constructor with an argument 
MyString::MyString(char const* chars) 
{ 
    if(chars) 
    { 
     size = strlen(chars); 
     value = new char[size]; 
     memcpy(value, chars, size); 
    } 
    else 
    { 
     value = new char[1]; 
     *value = 0; 
     size = 0; 
    } 
} 

//find length 
int MyString::length() const 
{ 
    return size; 
} 

//find the value of each index 
char& MyString::operator[](int index) 
{ 
    return value[index]; 
} 

//operator + (concatenate) 
MyString operator+(const MyString& newWord, const MyString& newWord2) 
{ 
    MyString concatenated; 
    concatenated.value = new char[newWord.size + newWord2.size + 1]; 
    memcpy(concatenated.value, newWord.value, newWord.size); 
    memcpy(concatenated.value + newWord.size, newWord2.value, newWord2.size + 1); 
    return concatenated; 
} 

//operator += (append) 
MyString& MyString::operator+=(const MyString& newWord) 
{ 
    if(newWord.size > 0) 
    { 
     char * newMemory = value; 
     value = new char[size + newWord.size + 1]; 
     memcpy(value, newMemory, size); 
     memcpy(value + size, newWord.value, newWord.size); 
     delete[] newMemory; 
     size += newWord.size; 
    } 
    return *this; 
} 

//ostream operator 
ostream& operator<<(ostream& newWord, const MyString& newWord2) 
{ 

    newWord << newWord2.value; 
    return newWord; 
} 

//istream operator 
istream& operator >>(istream& newWord, MyString& newWord2) 
{ 
    std::vector<char> v; 
    for(;;) 
    { 
     char c = newWord.get(); 
     if(newWord.eof() || isspace(c)) 
     { 
      break; 
     } 
     v.push_back(c); 
    } 
    if(!v.empty()) 
    { 
     newWord2 = v.data(); 
    } 
    return newWord; 
} 

//all boolean operators 
bool operator==(const MyString& newWord, const MyString& newWord2) 
{ 
    return strcmp(newWord.value, newWord2.value) == 0; 
} 

bool operator!=(const MyString& newWord, const MyString& newWord2) 
{ 
    return !(newWord == newWord2); 
} 

bool operator<(const MyString& newWord, const MyString& newWord2) 
{ 
    return strcmp(newWord.value, newWord2.value) < 0; 
} 
bool operator>(const MyString& newWord, const MyString& newWord2) 
{ 
    return strcmp(newWord.value, newWord2.value) < 0; 
} 

bool operator<=(const MyString& newWord, const MyString& newWord2) 
{ 
    return !(newWord > newWord2); 
} 

bool operator>=(const MyString& newWord, const MyString& newWord2) 
{ 
    return !(newWord < newWord2); 
} 

//destructor to release memory 
MyString::~MyString() 
{ 
    delete[] value; 
} 
+0

あなたが提案したコードを実装しようとすると、このエラーが発生します。ConsoleApplication5.exeの0x0F5E0E09(ucrtbased.dll)で例外がスローされました:0xC0000005:0x005D2000という場所にアクセス違反が発生しました。このアイデアはありますか?申し訳ありませんが、私はC++を2ヶ月使っています。あなたの大きな助けをありがとう! –

+0

これは、実際のエラーの内容を推測するには情報が少なすぎます。あなたに役立つかもしれないコードをいくつか追加しました。 – Aconcagua

関連する問題