在C ++中读取文件时崩溃

时间:2013-03-11 12:04:42

标签: 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中,我发现在执行&#34; return result;&#34;之后发生了崩溃。在函数的倒数第二行,即当黄色光标用于函数的最后一个右括号时。 我收到了一条消息

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个字符&amp;如果这些字符中不存在该单词,那么我想跳转到下一行。最初我使用过myFile.getline(read, 20, '\n');但是在第一个循环之后,每个后续循环都会导致NULL传递给read。所以我读了1000,因为在读1000个字符之前它会找到&#39; \ n&#39; &安培;转到下一行。 实现这一目标的更好机制将非常有用。

4 个答案:

答案 0 :(得分:4)

为什么不使用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

答案 1 :(得分:3)

myFile.getline(read, 1000, '\n');将从地址read开始向内存中读取最多1000个字节。 read是一个20字节的堆栈缓冲区,因此您可能会超出已分配内存的末尾进行写入。这样做的效果是不确定的,但很可能发生崩溃。

要解决此问题,您应该将read缓冲区的大小传递给getline;

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

(注意sizeof(read)仅适用于堆栈缓冲区。如果在堆上分配readsizeof只会告诉您指针的大小而不是分配的内存指向。)

答案 2 :(得分:0)

在您可以使代码生效之前,请忘记char[]。 (如 其他人指出,你有一个缓冲区溢出。很容易 与任何C样式数组作为局部变量。)因为你是 寻找单词,初始代码可以是简单的东西 as:

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

这当然可以更快,但如果"LastWord"不是 在文件很远的地方,可能没有必要。 (BYW:是的 通常不需要关闭输入中使用的文件。该 析构函数会处理这个,因为你已经检查了 无论如何,每次输入后的状态,都没有错误检查 担心。)

答案 3 :(得分:0)

我在上面的代码中可以想到的一个地方导致缓冲区溢出:

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;

}