我正在阅读ptree
的各种数据。其中一个字段声明为
char * segmentCode;
所以我以这种方式读取segmentCode:
segmentCode = dataTree.get<char*>("segmentCode");
但是,它会引发访问冲突。我哪里做错了?
解决方法很难看:
string tmpStr = dataTree.get<string>("segmentCode");
segmentCode = strdup(tmpStr.c_str());
答案 0 :(得分:3)
使用char *作为segmentCode的原因是什么?在C ++世界中,首选是使用其他对象来管理相关数据(例如,std :: string,std :: vector&lt;&gt;)
如果我们查看ptree.hpp标题:
/**
* A property tree with std::string for key and data, and default
* comparison.
*/
typedef basic_ptree<std::string, std::string> ptree;
我们可以看到ptree在内部使用std :: string作为其键和值。这意味着ptree的首选数据格式是std :: string。
因此建议使用:
std::string segmentCode = dataTree.get<std::string>("segmentCode");
这比您的解决方法更有效,因为字符串只应被复制一次(来自ptree)。虽然strdup
将创建另一个副本,然后需要稍后显式调用free
。
-
现在关于访问违规的来源......
如果我们看一下basic_tree::get<Type>()
方法:
/** Shorthand for get_child(path).get_value\<Type\>(). */
template<class Type>
Type get(const path_type &path) const;
我们看到此调用basic_tree::get_value<Type>()
:
/** Take the value of this node and attempt to translate it to a
* @c Type object using the default translator.
* @throw ptree_bad_data if the conversion fails.
*/
template<class Type>
Type get_value() const;
请注意提及类型转换和默认翻译。
在调用堆栈的下方,我们发现访问冲突点实际上在转换过程中,可以在stream_translator.hpp(customize_stream :: extract)中找到:
static void extract(std::basic_istream<Ch, Traits>& s, E& e) {
s >> e;
if(!s.eof()) {
s >> std::ws;
}
}
以这种方式使用流是在类型之间进行一般转换的常用技术。特别是当转换为/来自的类型之一是字符串时。
这里的问题是get<char*>
定义了存储类型(我们将值放在哪里)作为char指针。从ptree的角度来看,这被认为是一个可以保存值的完整类型,而转换流将其视为指向可以写入的内存区域的指针。
这相当于:
std::istringstream iss("value");
char * p; // uninitialized pointer
iss >> p; // write to some random memory location
是发生访问冲突的原因。
再次传递给get<Type>
的 Type 应该能够保存完整的值。