在visual c++中的fgets()上接收访问冲突错误

Receiving access violation error on fgets() in visual c++

本文关键字:访问冲突 错误 visual c++ 中的 fgets      更新时间:2023-10-16

在Visual studio上运行以下代码时,出现访问冲突错误。也许我正在尝试读取一些我没有分配的指针位置或其他什么,但我似乎找不到问题的确切位置。需要一些帮助。

#include <iostream>
class fileReader
{
public:
    FILE *fp;
    char** lines;
    fileReader()
    {
        fp = NULL;
    }
    fileReader(char* path)
    {
        int j=0;
        fp = fopen(path,"r");
        if (fp == NULL) 
            return;
        else 
        {
            lines = (char**) malloc(sizeof(char *)*56000);
            for (int i=0; i<56000; i++)
                lines[i] = (char*)malloc(sizeof(char)*1440);
            while ( fgets(lines[j], 1440, fp) )
                j++;
            fclose(fp);
        }
    }
};
int main(int argv, char** argc)
{
    char* path = "D:\testfile.txt";
    fileReader *p = new fileReader(path);
    for (int i=0; i<2; i++)
        std::cout<<p->lines[i];
    return 0;
}

j上没有超过lines:中元素数量的保护

while ( fgets(lines[j], 1440, fp) )
    j++; 

若文件包含的行数超过56000,则这将访问超出数组的范围。

由于这是C++,您应该考虑使用ifstreamstd::getline()std::vector<std::string>来读取文件。std::vector<std::string>将为您管理内存分配:

std::vector<std::string> lines;
std::ifstream in("D:\testfile.txt");
if (in.is_open())
{
    std::string line;
    while (std::getline(in, line))
    {
        lines.push_back(line);
    }
    in.close();
}

您没有检查malloc:的返回值

 lines = (char**) malloc(sizeof(char *)*56000);
 for (int i=0; i<56000; i++)
     lines[i] = (char*)malloc(sizeof(char)*1440);

如果malloc失败,则返回NULL

你试图分配相当多的内存,所以我从那里开始。

如果fopen失败会发生什么?我看到一些未初始化的指针在这种情况下四处漂浮。在不太可能的情况下,malloc如果失败,则会有一些空指针,而这些指针不应该是取消引用。你不能确保至少有两行在main中执行循环之前实际阅读;如果没有,你就是将尝试输出未初始化的数据。更不用说你永远不会释放你分配的内存。

(FWIW:使用您的策略,j应该是公共的,但fp可以是本地的至FileReader::FileReader。)

与此几乎完全等效的方法是使用:

std::vector<std::vector<char> > lines;
//  ...
FileReader( char const* path )
    : lines( 56000, std::vector<char>( 1440 ) ) 
{
    //  ...
}

唯一的区别是对fgets的调用CCD_ 18。

我可能更喜欢使用std::vector<std::string>,初始化清空,然后对每行进行推回读取:

FileReader( char const* path )
{
    std::ifstream input( path );
    std::string line;
    while ( std::getline( input, line ) ) {
        lines.push_back( line + 'n' );
    }
}

简单得多,它解决了你遇到的大多数问题。(实际上,我可能会检查文件是否正确打开分别地如果不能,通常会给出错误消息打开输入,而不是将其视为空文件。)

当然,没有理由在main中使用new。只是:

int
main()
{
    FileReader file( "D:/testfile.txt" );
    for ( size_t i = 0; i != file.lines.size(); ++ i ) {
        std::cout << file.lines[i];
    }
    return std::cout.flush() ? EXIT_SUCCESS : EXIT_FAILURE;
}