【发布时间】:2020-01-13 14:18:12
【问题描述】:
以下简单代码(二进制文件处理)在与适用于 Windows 的 Codeblocks 17.12 (mingw32-g++) 捆绑的编译器上运行良好,但在适用于 Linux 的 g++ 9.2.1(在 Ubuntu 19.10 上)出现分段错误:
#include <iostream>
#include <fstream>
using namespace std;
class A {
public:
int x;
string y;
};
int main()
{
ofstream k;
A m;
m.x = 10;
m.y = "Hello";
k.open("file.dat", ios::binary);
k.write(reinterpret_cast<char *>(&m), sizeof(A));
k.close();
ifstream i;
A t;
i.open("file.dat", ios::binary);
i.seekg(0, ios::beg);
i.read(reinterpret_cast<char *>(&t), sizeof(A));
cout << t.x << " " << t.y;
i.close();
return 0;
}
我是不是做错了什么,Windows 上最小的 g++ 可以原谅我,但 g++-Linux 不是?还是我发现了一个错误?
【问题讨论】:
-
您的代码调用了未定义的行为。将对象所在的内存写入文件是不正确的序列化。在线搜索该术语以获取更多信息。
-
只有POD types没有指针,你才能读取或写入原始对象。
std::string基本上是指向堆分配数据和字符串大小的指针(小字符串优化除外),因此您无法将原始std::string对象读取或写入文件。 -
或者我发现了一个错误? -- 编译器中的一个错误?不,您的代码中有错误吗?是的。此外,如果您记下
write和read的最后一个参数,这将不起作用。sizeof(A)永远不会改变并且是编译时值。如果std::string成员中有一百万个字符,sizeof(A)将不会改变。 -
@UtkarshGupta 未定义的行为就是这样——未定义。如果您更改编译器选项,同样的代码可能会失败。
-
另外,试试我提到的案例。将
y设为一千个字符而不是五个字符。您将看到您的代码失败。例如,m.y = std::string(1000, 'x');您在输出文件中看到 1,000 个“x”字符吗?
标签: c++ file-handling