RapidXML从文件中读取 - 这里有什么问题?

时间:2011-06-15 20:11:13

标签: c++ file-io libcurl rapidxml code-formatting

这两种读取输入文件的方法有什么区别?

1)使用'ifstream.get()'

2)vector<char>使用ifstreambuf_iterator<char>(我不太了解!)

(除了使用漂亮的矢量方法的明显答案之外)

输入文件是XML,如下所示,立即解析为rapidxml文档。 (在别处初始化,参见示例main函数。)

首先,让我向您展示两种编写'load_config'函数的方法,一种使用ifstream.get(),另一种使用vector<char>

方法1 ifstream.get()提供工作代码和安全的rapidXML文档对象:

rapidxml::xml_document<> *load_config(rapidxml::xml_document<> *doc){
   ifstream myfile("inputfile");

   //read in config file
   char ch;
   char buffer[65536];
   size_t chars_read = 0;

   while(myfile.get(ch) && (chars_read < 65535)){
      buffer[chars_read++] = ch;
   }
   buffer[chars_read++] = '\0';

   cout<<"clearing old doc"<<endl;
   doc->clear();

   doc->parse<0>(buffer);

   //debug returns as expected here
   cout << "load_config: Name of my first node is: " << doc->first_node()->name() << "\n";

   return doc;
}

方法2导致另一个库的cloberred rapidXML文档 - 特别是对curl_global_init(CURL_GLOBAL_SSL)的调用[参见下面的主要代码] - 但我还没有把它归咎于curl_global_init。

rapidxml::xml_document<> *load_config(rapidxml::xml_document<> *doc){
   ifstream myfile("inputfile");

   vector<char> buffer((istreambuf_iterator<char>(inputfile)), 
                istreambuf_iterator<char>( ));
   buffer.push_back('\0');

   cout<<"file looks like:"<<endl;  //looks fine
   cout<<&buffer[0]<<endl;

   cout<<"clearing old doc"<<endl;
   doc->clear();

   doc->parse<0>(&buffer[0]);

   //debug prints as expected
   cout << "load_config: Name of my first node is: " << doc->first_node()->name() << "\n";

   return doc;
}

主要代码:

int main(void){
   rapidxml::xml_document *doc;
   doc = new rapidxml::xml_document;

   load_config(doc);

   // this works fine:
   cout << "Name of my first node is: " << doc->first_node()->name() << "\n"; 

   curl_global_init(CURL_GLOBAL_SSL);  //Docs say do this first.

   // debug broken object instance:
   // note a trashed 'doc' here if using vector<char> method 
   //  - seems to be because of above line... name is NULL 
   //    and other nodes are now NULL
   //    causing segfaults down stream.
   cout << "Name of my first node is: " << doc->first_node()->name() << "\n"; 

我非常确定这一切都是在一个线程中执行的,但也许有些事情在我的理解之外。

我也担心我只修改了一个症状,而不是原因......只需更改我的文件加载功能即可。在这里寻求社区的帮助!

问题:为什么从矢量转移到字符数组会解决这个问题?

提示:我知道rapidXML使用了一些实际上直接访问输入字符串的聪明的内存管理。

提示:上面的主要功能创建了一个动态(新)xml_document。这不在原始代码中,并且是调试更改的工件。原始(失败)代码声明了它并且没有动态分配它,但是发生了相同的问题。

完全公开的另一个提示(虽然我不明白为什么这很重要) - 在这个混乱的代码中有另一个向量实例,由rapidxml :: xml_document对象中的数据填充。

1 个答案:

答案 0 :(得分:5)

两者之间的唯一区别是vector版本正常工作,char数组版本在文件长度超过65535个字符时会导致未定义的行为(它将\0写入第65535或65536位,超出界限。

两个版本常见的另一个问题是,您将文件读入的内存的生命周期比xml_document短。 阅读文档:

  

字符串必须在文档的生命周期内保持不变。

load_config退出时,vector被销毁,内存被释放。尝试访问该文档会导致读取无效内存(未定义的行为)。

char阵列版本中,内存在堆栈上分配。当load_config存在时,它仍然被“释放”(访问它会导致未定义的行为)。但你没有看到崩溃,因为它还没有被覆盖。