-1

ファイル内の特定の単語を検索して、その単語がファイル内に存在するかどうかの結果を返したい。これを行う関数を作成しました。しかし、プログラムを返す間、プログラムはクラッシュします。コードは次のとおりです。

bool FindMyWord(const char *fileName)
{
    ifstream myFile (fileName);
    if(!myFile)
        return false;

    string wordSearch = "MyWord";
    string endSearch = "LastWord";
    bool result;
    while(1)
    {
        char read[20];
        myFile.getline(read, 1000, '\n');
        string line(read, read+20);
        if(line.find(wordSearch) != string::npos)
        {
            result = true;
            break; //comes here after looping about 10 times
        }
        if(line.find(endSearch) != string::npos)
        {
            result = false;
            break;
        }
    }
    myFile.close();
    return result;
} // <- crash when F10 is pressed after this

VS2010でデバッグ中return result;に、関数の最後から2番目の行で ""を実行した後、つまり黄色のカーソルが関数の最後の閉じ括弧にあるときにクラッシュが発生していることがわかりました。メッセージが届きます

A buffer overrun has occurred in myApp.exe which has corrupted the program's internal
state. Press Break to debug the program or Continue to terminate the program.

このエラーは何ですか?私はこのような関数を呼び出しています:

bool result = FindMyWord("myFileName.stp");

更新:各行の文字数はさまざまで、20を超えています。最初の20文字を読みたいのですが、それらの文字に単語が存在しない場合は、次の行にジャンプします。最初は使用していましたがmyFile.getline(read, 20, '\n');、最初のループの後、後続のすべてのループの結果、読み取りにNULLが渡されました。1000文字を読み取る前に'\n'が見つかり、次の行に移動するため、1000を読み取るようにしました。同じことを達成するためのより良いメカニズムは非常に役立ちます。

4

4 に答える 4

4

std::string固定長バッファの代わりに a を使用しないのはなぜですか?

bool FindMyWord(const char *fileName)
{
    std::ifstream myFile (fileName);
    if(!myFile) {
        return false;
    }

    std::string wordSearch = "MyWord";
    std::string endSearch = "LastWord";
    bool result;
    std::string line;
    while(std::getline(myFile, line))
    {
        if(line.find(wordSearch) != std::string::npos)
        {
            result = true;
            break; //comes here after looping about 10 times
        }
        if(line.find(endSearch) != std::string::npos)
        {
            result = false;
            break;
        }
    }
    myFile.close();
    return result;
} 

バッファ オーバーフローは、非常に多くのセキュリティ問題の原因となっています。固定長バッファを使用しないでください。

これは、ストリームのエラーをチェックするため、もう少し正確です。

PS私は嫌いusing namespace stdです!

于 2013-03-11T12:13:24.200 に答える
3

myFile.getline(read, 1000, '\n');address から始まるメモリに最大 1000 バイトを読み込みますreadreadは 20 バイトのスタック バッファであるため、割り当てられたメモリの末尾を超えて書き込むリスクがあります。これを行った場合の影響は未定義ですが、クラッシュする可能性が非常に高くなります。

これを修正するには、readバッファのサイズをgetline;に渡す必要があります。

myFile.getline(read, sizeof(read), '\n');

sizeof(read)(スタックバッファに対してのみ機能することに注意してください。readヒープに割り当てられた場合sizeof、ポインタが指す割り当てられたメモリではなく、ポインタのサイズのみがわかります。)

于 2013-03-11T12:07:35.910 に答える
0

上記のコードでバッファオーバーランを引き起こしていると考えられる場所の1つは次のとおりです。

myFile.getline(読み取り、1000、'\n');

'read' は 20 文字分のスペースを持つバッファーなので、ファイルがそれよりも大きな行を取得した場合は格納できません。

また、eof チェックを行ってください。私は次のようなことを提案します:


bool FindMyWord(const char *fileName)
{
    if(!myFile)
        return false;

ifstream myFile (fileName);

const char* wordSearch = "MyWord";
const char* endSearch  = "LastWord";
bool result = false;
string line;

while(std::getline(myFile, line))
{
    if(line.find(wordSearch, 0, 20) != string::npos)
    {
        result = true;
        break; //comes here after looping about 10 times
    }

    if(line.find(endSearch, 0, 20) != string::npos)
    {
        result = false;
        break;
    }
}

myFile.close();
return result;

}

于 2013-03-11T12:51:00.240 に答える
0

コードが機能するようになるまでは、char[]. (他の人が指摘しているように、バッファ オーバーランがあります。C スタイルの配列をローカル変数として使用するのは非常に簡単です。) 単語を探しているので、最初のコードは次のように単純なものにすることができます。

std::string word;
while ( myFile >> word && word != "MyWord" && word != "LastWord" ) {
}
return word == "MyWord";

これは確かに高速化できますが"LastWord"、ファイルにそれほど遠くない場合は必要ないかもしれません。(BYW: 通常、入力に使用されたファイルを閉じる必要はありません。デストラクタがそれを処理します。いずれにせよ、各入力の後にステータスをチェックしたので、心配するエラー チェックはもうありません。)

于 2013-03-11T12:16:32.593 に答える