簡體   English   中英

在C ++中讀取文件時崩潰

[英]Crash while reading a File in C++

我想搜索文件中的特定單詞並返回關於該單詞是否存在於文件中的結果。 我創建了一個函數來執行此操作。 但是在返回程序時崩潰了。 這是代碼:

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; ”后發生的。 我收到消息

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,因為在讀取1000個字符之前,它將找到'\\ n'並轉到下一行。 一個更好的實現相同目標的機制將非常有幫助。

為什么不使用std::string而不是固定長度的緩沖區?

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

myFile.getline(read, 1000, '\\n'); read地址開始將從內存中讀取多達1000個字節。 read是一個20字節的堆棧緩沖區,因此您有寫超出分配的內存末尾的風險。 這樣做的效果是不確定的,但很可能發生崩潰。

為了解決這個問題,您應該將read緩沖區的大小傳遞給getline ;

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

(請注意, sizeof(read)僅適用於堆棧緩沖區。如果read是在堆上分配的,則sizeof僅會告訴您指針的大小,而不是指針所指向的已分配內存。)

在使代碼正常工作之前,請忽略char[] (正如其他人指出的那樣,您有一個緩沖區溢出。使用任何C樣式數組作為局部變量都非常容易。)由於您要查找單詞,因此初始代碼可以很簡單:

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

當然可以加快速度,但是如果"LastWord"離文件不太遠,則可能沒有必要。 (BYW:通常不必關閉輸入中使用的文件。析構函數將解決此問題,並且由於您在每次輸入后都檢查了狀態,因此無需擔心其他錯誤。)

我在上面的代碼中想到的一個導致緩沖區溢出的地方是:

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

由於“讀取”是一個可容納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;

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM