尝试使用重载运算符读取二进制文件时出现分段错误 >>
segmentation fault when try reading binary file using overloaded operator >>
我正在尝试读取一个用类似代码创建的二进制文件:
#include <list>
#include <string>
#include <bitset>
#include <fstream>
struct Node {
char data;
int frequency;
friend std::istream& operator>>(std::istream& input, Node& e) {
input.read(&e.data, sizeof(e.data));
input.read(reinterpret_cast<char*>(e.frequency), sizeof(e.frequency));
return input;
};
friend std::ostream& operator<<(std::ostream& output, const Node& e) {
output.write(&e.data, sizeof(e.data));
output.write(reinterpret_cast<const char*>(&e.frequency), sizeof(e.frequency));
return output;
};
};
int main() {
std::list<struct Node> list;
for(char i='a'; i<='z'; i++) {
struct Node n;
n.data = i;
n.frequency = 1;
list.push_back(n);
}
std::string encoded_file = "";
for(int i=0; i<100; i++) {
encoded_file = encoded_file + "101010";
}
std::fstream output;
output.open("output.txt", std::ios_base::out | std::ios_base::binary);
if (output.is_open()) {
output << list.size();
for(int i=0; i<list.size(); i++) {
output << list.front();
list.pop_front();
}
for(long unsigned int i=0; i<encoded_file.length(); i+=8) {
std::string data = encoded_file.substr(i, 8);
std::bitset<8> b(data);
unsigned long x = b.to_ulong();
unsigned char c = static_cast<unsigned char>( x );
output << c;
}
}
output.close();
return 0;
}
此代码似乎工作正常,文件 output.txt
生成没有问题。
但是,当我尝试使用以下代码读取文件时:
#include <list>
#include <string>
#include <bitset>
#include <fstream>
#include <iostream>
struct Node {
char data;
int frequency;
friend std::istream& operator>>(std::istream& input, Node& e) {
input.read(&e.data, sizeof(e.data));
input.read(reinterpret_cast<char*>(e.frequency), sizeof(e.frequency));
return input;
};
friend std::ostream& operator<<(std::ostream& output, const Node& e) {
output.write(&e.data, sizeof(e.data));
output.write(reinterpret_cast<const char*>(&e.frequency), sizeof(e.frequency));
return output;
};
};
int main() {
std::list<struct Node> list;
std::string encoded_file = "";
std::fstream input;
input.open("output.txt", std::ios_base::in | std::ios_base::binary);
if (input.is_open()) {
std::cout << "1" << std::endl;
int size = 0;
input >> size;
std::cout << "size: " << size << std::endl;
for(int i=0; i<size; i++) {
Node node;
input >> node;
std::cout << node.data << " (" << node.frequency << ")" << std::endl;
list.push_back(node);
}
std::cout << "2" << std::endl;
char c;
while(input.get(c)) {
std::bitset<8> b(c);
encoded_file = encoded_file + b.to_string();
}
std::cout << "3" << std::endl;
}
input.close();
return 0;
}
我遇到了分段错误。当我尝试执行 input >> node;
时发生错误。我检查了一下,显然当程序进入Node::operator>>
时,读取了e.data
,但没有读取频率。
任何人都可以告诉我如何解决这个问题吗?
您的 Node::operator>>
中有错字。阅读 e.frequency
时,您缺少一个 &
:
input.read(reinterpret_cast<char*>(&e.frequency), sizeof(e.frequency));
^
那是我的 中的错字,您是从哪里获得此代码的。我已经纠正了那个错误。
话虽如此,我发现您的代码中还有其他问题。
您正在以二进制模式创建文件,但并未将所有内容都作为二进制值流式传输到其中。只有您的 Node
class 以二进制形式流式传输,但您的其他值以文本形式流式传输。不要混合格式方案。
output << list.size()
和 output << c
正在执行格式化 I/O。对于二进制 I/O,使用 write()
而不是 operator<<
,例如:
size_t size = list.size();
output.write(reinterpret_cast<char*>(&size), sizeof(size));
...
unsigned char c = ...;
output.write(reinterpret_cast<char*>(&c), sizeof(c));
然后在读取文件时逆向进行,eg:
input.read(reinterpret_cast<char*>(&size), sizeof(size));
...
unsigned char c;
while(input.read(reinterpret_cast<char*>(&c), sizeof(c))) {
...
}
此外,在创建文件的代码中,第一个 for
循环是错误的。您正在修改 list
并循环遍历它,从而影响它的 size()
。所以你最终跳过了列表中的节点。您应该使用迭代器而不是索引进行迭代,并且根本不修改列表,例如:
for(std::list<Node>::const_iterator iter = list.cbegin(); iter != list.cend(); ++iter) {
output << *iter;
}
或更简单:
for(const auto &item : list) {
output << item;
}
我正在尝试读取一个用类似代码创建的二进制文件:
#include <list>
#include <string>
#include <bitset>
#include <fstream>
struct Node {
char data;
int frequency;
friend std::istream& operator>>(std::istream& input, Node& e) {
input.read(&e.data, sizeof(e.data));
input.read(reinterpret_cast<char*>(e.frequency), sizeof(e.frequency));
return input;
};
friend std::ostream& operator<<(std::ostream& output, const Node& e) {
output.write(&e.data, sizeof(e.data));
output.write(reinterpret_cast<const char*>(&e.frequency), sizeof(e.frequency));
return output;
};
};
int main() {
std::list<struct Node> list;
for(char i='a'; i<='z'; i++) {
struct Node n;
n.data = i;
n.frequency = 1;
list.push_back(n);
}
std::string encoded_file = "";
for(int i=0; i<100; i++) {
encoded_file = encoded_file + "101010";
}
std::fstream output;
output.open("output.txt", std::ios_base::out | std::ios_base::binary);
if (output.is_open()) {
output << list.size();
for(int i=0; i<list.size(); i++) {
output << list.front();
list.pop_front();
}
for(long unsigned int i=0; i<encoded_file.length(); i+=8) {
std::string data = encoded_file.substr(i, 8);
std::bitset<8> b(data);
unsigned long x = b.to_ulong();
unsigned char c = static_cast<unsigned char>( x );
output << c;
}
}
output.close();
return 0;
}
此代码似乎工作正常,文件 output.txt
生成没有问题。
但是,当我尝试使用以下代码读取文件时:
#include <list>
#include <string>
#include <bitset>
#include <fstream>
#include <iostream>
struct Node {
char data;
int frequency;
friend std::istream& operator>>(std::istream& input, Node& e) {
input.read(&e.data, sizeof(e.data));
input.read(reinterpret_cast<char*>(e.frequency), sizeof(e.frequency));
return input;
};
friend std::ostream& operator<<(std::ostream& output, const Node& e) {
output.write(&e.data, sizeof(e.data));
output.write(reinterpret_cast<const char*>(&e.frequency), sizeof(e.frequency));
return output;
};
};
int main() {
std::list<struct Node> list;
std::string encoded_file = "";
std::fstream input;
input.open("output.txt", std::ios_base::in | std::ios_base::binary);
if (input.is_open()) {
std::cout << "1" << std::endl;
int size = 0;
input >> size;
std::cout << "size: " << size << std::endl;
for(int i=0; i<size; i++) {
Node node;
input >> node;
std::cout << node.data << " (" << node.frequency << ")" << std::endl;
list.push_back(node);
}
std::cout << "2" << std::endl;
char c;
while(input.get(c)) {
std::bitset<8> b(c);
encoded_file = encoded_file + b.to_string();
}
std::cout << "3" << std::endl;
}
input.close();
return 0;
}
我遇到了分段错误。当我尝试执行 input >> node;
时发生错误。我检查了一下,显然当程序进入Node::operator>>
时,读取了e.data
,但没有读取频率。
任何人都可以告诉我如何解决这个问题吗?
您的 Node::operator>>
中有错字。阅读 e.frequency
时,您缺少一个 &
:
input.read(reinterpret_cast<char*>(&e.frequency), sizeof(e.frequency));
^
那是我的
话虽如此,我发现您的代码中还有其他问题。
您正在以二进制模式创建文件,但并未将所有内容都作为二进制值流式传输到其中。只有您的 Node
class 以二进制形式流式传输,但您的其他值以文本形式流式传输。不要混合格式方案。
output << list.size()
和 output << c
正在执行格式化 I/O。对于二进制 I/O,使用 write()
而不是 operator<<
,例如:
size_t size = list.size();
output.write(reinterpret_cast<char*>(&size), sizeof(size));
...
unsigned char c = ...;
output.write(reinterpret_cast<char*>(&c), sizeof(c));
然后在读取文件时逆向进行,eg:
input.read(reinterpret_cast<char*>(&size), sizeof(size));
...
unsigned char c;
while(input.read(reinterpret_cast<char*>(&c), sizeof(c))) {
...
}
此外,在创建文件的代码中,第一个 for
循环是错误的。您正在修改 list
并循环遍历它,从而影响它的 size()
。所以你最终跳过了列表中的节点。您应该使用迭代器而不是索引进行迭代,并且根本不修改列表,例如:
for(std::list<Node>::const_iterator iter = list.cbegin(); iter != list.cend(); ++iter) {
output << *iter;
}
或更简单:
for(const auto &item : list) {
output << item;
}