C++ Can';t将类对象数组写入/读取到文件

C++ Can';t将类对象数组写入/读取到文件,c++,file,fstream,C++,File,Fstream,我有一个类用户,有3个参数:id、pass、active 我想将用户对象数组写入一个文件,但它不起作用 有时是工作,但之后我只能读取这些参数:id,active 参数pass给了我:无、一些字符或一个字符(几乎是“a”) 班级: class User { int id; char *pass; bool active; public: User() { id = -1; pass = NULL; active = 0

我有一个类用户,有3个参数:id、pass、active

我想将用户对象数组写入一个文件,但它不起作用

有时是工作,但之后我只能读取这些参数:id,active

参数pass给了我:无、一些字符或一个字符(几乎是“a”)

班级:

class User {
    int id;
    char *pass;
    bool active;
public:
    User() {
        id = -1;
        pass = NULL;
        active = 0;
    }
    User(int id, char * pass, bool active = 1) {
        this->id = id;

        if (pass) delete[] pass;
        this->pass = new char[strlen(pass)];
        memcpy(this->pass, pass, strlen(this->pass));

        this->active = active;
    }

    void set_id(int id) {
        this->id = id;
    }
    void set_active(bool active) {
        this->active = active;
    }
    void set_pass(char *pass) {
        this->pass = new char[strlen(pass)];
        memcpy(this->pass, pass, strlen(this->pass));
    }

    int get_id() {
        return id;
    }
    char *get_pass() {
        return pass;
    }
    bool get_active() {
        return active;
    }
};
这是我的阵列:

User *users = new User[999999]; int size_ = 0;
主要内容:

intmain(){
fstream r|u user(“user.txt”,ios::binary | ios::in);
如果(!r_用户){
r_user.close();
charpass[100];

cerr您的代码在处理pass存储的方式中遇到了两个关键错误

您使用:

    this->pass = new char[strlen(pass)];
    memcpy(this->pass, pass, strlen(this->pass));
请注意,任何字符串都以空字节结尾,因此要复制的数据大小为strlen(pass)+1。例如:strlen(“abcedf”)==6,但需要7个字节来存储它

结果可能是戏剧性的:当尝试读取字符串时,软件将命中连接到此区域的其他内存块,并将读取错误的字符串(因为没有空字节会停止字符串读取).随着时间的推移,有了更多的函数,这个小错误可能会将内存泄漏到文件中,可能会导致崩溃或以一个接一个的方式写入空字节,函数会停止正常工作,一切都会变得越来越糟…听起来像地狱,嗯

    this->pass = new char[strlen(pass) + 1];
    memcpy(this->pass, pass, strlen(this->pass) + 1);
或者,更优雅一些:

    this->pass = new char[strlen(pass) + 1];
    this->pass = strcpy(this->pass, pass);
或者更优雅、更安全:

    this->pass = strdup(pass);
您可能还想为这种管理使用一个独特的私有函数,实际上这个敏感部分在您的代码中是重复的

也许可以把通行证弄散开?:-)如果你想做一件严肃的工作,就去找Bcrypt:

我还看到你使用了一个指针来传递信息,所以你保存了指针,但没有保存指向的数据

加载指针值时,内存中没有任何内容,或者如果内存中有某些内容,则肯定不是您的过程(从未保存)。您必须使用静态缓冲区来存储该过程,并确保您的类将保持POD(纯旧数据)

通过使用哈希密码,您的最终缓冲区将具有确定的大小。例如:

char bcrypt_password[64];
而不是:

char *pass;
但要注意你的分配:

 new User[999999];
会消耗大量的内存


我就是你,我会对你的对象进行序列化,并集成import()export()方法。基本的CSV序列化将允许以后的DB导入/导出。

fstream
只转储原始数据,因此它只对常规变量有效

pass
char*
,因此它存储的是指针地址而不是字符串值

您的类需要自定义序列化。
将方法添加到用户类中,以
Load()
Save()
处理
pass
变量。它们应该接受
fstream
缓冲区,以便对其进行读/写。

您是如何创建User.txt的?@zdat,文件自动创建的,如果
w\u User.write(reinterpret\u cast(users)则检查其中的内容,size_*sizeof(User));
注定会失败。成员
char*pass;
将向文件中写入指针,而不是指针引用的数据。当您试图读回该文件时,谁知道该地址是否可以安全使用?非主题:在
用户(int-id,char*pass,bool-active=1)
if(pass)delete[]pass;
在使用前消除传入的参数
pass
strlen(pass)
进入未定义的行为。如果您的任务未禁止,请使用
std::string
。是的,这是因为char*pass。现在我可以从文件中获取pass。
 new User[999999];