VC ++上的访问冲突错误

时间:2012-03-19 08:29:23

标签: c++ visual-c++ file-io

为什么我得到"访问违规错误阅读"在以下计划中:

错误在while循环上读取文件。

#include <iostream>

class fileReader
{
public:
    FILE *fp;
    char** lines;
    fileReader()
    {
        fp = NULL;
    }
    fileReader(const char* path)
    {
        int i=0;
        fp = fopen(path,"r");
        while ( fgets(lines[i], 100, fp) )
            i++;
    }
};

int main(int argv, char** argc)
{
    const char* path = "D:\\PS4263-2.txt";
    fileReader *p = new fileReader(path);
    for (int i=0; i<2; i++)
        std::cout<<p->lines[i];
    return 0;
}

修改

正如答案中提到的,我将代码更改为(下方),但我仍然遇到同样的错误。

#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;
}

3 个答案:

答案 0 :(得分:1)

char** lines;

从未分配任何记忆!
为了能够用它做任何有意义的事情,你需要分配足够的内存来保存你想要保存在其中的内容。

另见旁注,

  • 一旦完成其使用,您永远不会通过调用p来释放分配给delete p;的动态内存,这会给您一个未定义的行为。
  • 您永远不会检查标准库函数的返回值,您应该始终这样做。

答案 1 :(得分:1)

您的代码中存在许多问题:

  1. char** lines尚未分配。您需要分配lineslines[i]
  2. 您永远不会检查文件是否真的打开。使用前请检查fp
  3. 您忘了在最后关闭文件指针。致电fclose(fp)
  4. 编辑:

    您尚未取消分配lineslines[i]p。请注意,您必须free()使用lineslines[i]使用deletep

答案 2 :(得分:1)

此代码存在许多问题。但主要是,问题是你正在写一些邪恶的C / C ++混合。选择两种语言中的一种,并使用它。

以下是您的代码的修订版本:

#include <iostream>

class fileReader
{
public:
    FILE *fp;
    char** lines;
    fileReader() : fp(NULL) // initialization of members happens here
    {
        //fp = NULL; // anything here happens *after* initialization
        lines = new char*[100]; // let's just assume max 100 lines. We have to allocate space for them
        for (int i = 0; i < 100; ++i) {
            lines[i] = new char[100]; // allocate space for the contents of each individual line
        }
    }
    fileReader(const char* path)
    {
        lines = new char*[100]; // let's just assume max 100 lines. We have to allocate space for them
        for (int i = 0; i < 100; ++i) {
            lines[i] = new char[100]; // allocate space for the contents of each individual line
        }

        int i=0;
        fp = fopen(path,"r");
        while ( fgets(lines[i], 100, fp) )
            i++;
    }
    ~fileReader() {
        // deallocate and close our members:
        fclose(fp);
        for (int i = 0; i < 100; ++i) {
            delete[] lines[i]; // delete the contents of each line
        }
        delete[] lines; // delete the lines array
    }
};

int main(int argv, char** argc)
{
    const char* path = "D:\\PS4263-2.txt";
    fileReader p(path); // don't use new unless you really really have to
    for (int i=0; i<2; i++)
        std::cout<<p.lines[i];
    return 0;
}

现在至少它可以工作,如果每行包含少于100个字符 少于100行该文件存在且我们真正应该防范的十几个其他条件。特别是,我们在内存管理方面投入了大量精力:为所有行数据分配和释放空间。

但是,如果我们真正开始编写C ++,我们可以通过一些更改来做得更好。

#include <iostream> // we need this for the standard streams (cout)
#include <fstream> // we need proper C++ file streams too
#include <string> // C++ has strings. Don't waste your time on char pointers
#include <vector> // C++ has a dynamic array class. Don't use pointers as ad-hoc arrays

class fileReader
{
public:
    // FILE* fp; // no point in making this a class member, when it's only used in one function
    std::vector<std::string> lines; // use a vector of strings. Much easier to manage
    fileReader() // vectors are automatically initialized, no need to do anything
    {
    }
    fileReader(std::string path)
    {
        std::ifstream fp(path); // create an input file stream 
        std::string result; // store the contents of the current line here
        while (std::getline(fp, result)) {
                lines.push_back(result); // append the resulting line to the end of the vector
        }
    }
};

int main(int argv, char** argc)
{
    std::string path = "blah.txt";
    fileReader p(path); // don't use new unless you absolutely have to
    for (int i=0; i<2; i++)
        std::cout<<p.lines[i];
    return 0;
}

请注意,我们不再需要管理数组内存。当矢量和字符串超出范围时,它们会自动清理。由于我们不再使用new来分配fileReader,因此当 超出范围时,它会自动被删除。这有效地启动了一个连锁反应,其成员自己开始清理:文件流关闭,向量在询问其存储的字符串清理和关闭后释放其内存。并且整个程序折叠并关闭,而我们不必编写一行代码来处理它。