getline 在读取文本文件时有一个奇怪的行为
getline has a strange behaviour in reading a text file
我写的一段代码有一个奇怪的行为。有代码:
#include "pugixml.hpp"
#include <cassert>
#include <string>
#include <iostream>
#include <fstream>
#include <optional>
namespace xml = pugi;
void read_ascii_file(const std::string& filename)
{
std::ifstream file(filename, std::ios::in);
if(!file) {
std::cerr << "[ERREUR - read_ascii_file] Impossible d'ouvrir le fichier " << filename << "! Vérifier son existence." << std::endl;
abort();
}
std::string tmp;
while(std::getline(file, tmp))
{
//Do nothing here
}
file.close();
}
class Foo{
public:
Foo(const xml::xml_document& doc)
{
_base_node = doc.child("test");
std::string id = _base_node.child("data1").child_value("id");
std::cout << "id from constructor " << id <<std::endl;
}
void bar()
{
std::string id = _base_node.child("data2").child_value("id");
std::cout << "id from bar " << id <<std::endl;
}
private:
xml::xml_node _base_node;
};
std::optional<Foo> make(const std::string& filename)
{
xml::xml_document doc;
xml::xml_parse_result result = doc.load_file(filename.c_str());
if(result.status != xml::xml_parse_status::status_ok)
return {};
else
return Foo(doc);
}
int main()
{
std::string filename = "xml_test.dat";
std::optional<Foo> f = make(filename);
if(!f)
std::abort();
else
{
std::string filename = "lbl-maj_for_test.dat";
//read_ascii_file(filename);
f->bar();
}
return 0;
}
文件 xml_test.dat 是:
<test>
<data1>
<id>1</id>
</data1>
<data2>
<id>2</id>
</data2>
</test>
此代码给出输出:
id from constructor 1
id from bar 2
但是当我取消注释行 //read_ascii_file(filename);
时,输出变为:
id from constructor 1
Erreur de segmentation
gdb 给我错误:
#0 0x00007ffff7f84b20 in pugi::xml_node::child(char const*) const () from /lib/x86_64-linux-gnu/libpugixml.so.1
#1 0x00005555555578ba in Foo::bar (this=0x7fffffffdf40) at /home/guillaume/dev/C++/projects/moteur_de_calcul/test/test_xml_node.cpp:42
#2 0x00005555555575ec in main () at /home/guillaume/dev/C++/projects/moteur_de_calcul/test/test_xml_node.cpp:73
文件lbl-maj_for_test.dat是一个132行的txt文件,none好像长度超过了50个字符。我想到一个编码问题,但我不知道如何解决这个问题...
这与getline
无关。 Uncommenting/commenting 当你的程序有 未定义的行为时 会导致像这样的转移注意力。
问题是你的节点都是悬空的,因为你没有坚持doc
。当您调用 bar()
时,_base_node
是 dead/invalid/orphaned.
xml_document is the owner of the entire document structure; destroying the document destroys the whole tree.
假设库支持它,我会将doc
移动到Foo
并按值将其存储为成员。
我写的一段代码有一个奇怪的行为。有代码:
#include "pugixml.hpp"
#include <cassert>
#include <string>
#include <iostream>
#include <fstream>
#include <optional>
namespace xml = pugi;
void read_ascii_file(const std::string& filename)
{
std::ifstream file(filename, std::ios::in);
if(!file) {
std::cerr << "[ERREUR - read_ascii_file] Impossible d'ouvrir le fichier " << filename << "! Vérifier son existence." << std::endl;
abort();
}
std::string tmp;
while(std::getline(file, tmp))
{
//Do nothing here
}
file.close();
}
class Foo{
public:
Foo(const xml::xml_document& doc)
{
_base_node = doc.child("test");
std::string id = _base_node.child("data1").child_value("id");
std::cout << "id from constructor " << id <<std::endl;
}
void bar()
{
std::string id = _base_node.child("data2").child_value("id");
std::cout << "id from bar " << id <<std::endl;
}
private:
xml::xml_node _base_node;
};
std::optional<Foo> make(const std::string& filename)
{
xml::xml_document doc;
xml::xml_parse_result result = doc.load_file(filename.c_str());
if(result.status != xml::xml_parse_status::status_ok)
return {};
else
return Foo(doc);
}
int main()
{
std::string filename = "xml_test.dat";
std::optional<Foo> f = make(filename);
if(!f)
std::abort();
else
{
std::string filename = "lbl-maj_for_test.dat";
//read_ascii_file(filename);
f->bar();
}
return 0;
}
文件 xml_test.dat 是:
<test>
<data1>
<id>1</id>
</data1>
<data2>
<id>2</id>
</data2>
</test>
此代码给出输出:
id from constructor 1
id from bar 2
但是当我取消注释行 //read_ascii_file(filename);
时,输出变为:
id from constructor 1
Erreur de segmentation
gdb 给我错误:
#0 0x00007ffff7f84b20 in pugi::xml_node::child(char const*) const () from /lib/x86_64-linux-gnu/libpugixml.so.1
#1 0x00005555555578ba in Foo::bar (this=0x7fffffffdf40) at /home/guillaume/dev/C++/projects/moteur_de_calcul/test/test_xml_node.cpp:42
#2 0x00005555555575ec in main () at /home/guillaume/dev/C++/projects/moteur_de_calcul/test/test_xml_node.cpp:73
文件lbl-maj_for_test.dat是一个132行的txt文件,none好像长度超过了50个字符。我想到一个编码问题,但我不知道如何解决这个问题...
这与getline
无关。 Uncommenting/commenting 当你的程序有 未定义的行为时 会导致像这样的转移注意力。
问题是你的节点都是悬空的,因为你没有坚持doc
。当您调用 bar()
时,_base_node
是 dead/invalid/orphaned.
xml_document is the owner of the entire document structure; destroying the document destroys the whole tree.
假设库支持它,我会将doc
移动到Foo
并按值将其存储为成员。