What's the reasoning for using char * for segmentCode? In a C++ world the preference is to use other objects to manage associated data (e.g., std::string, std::vector<>)
If we look at the ptree.hpp header:
/**
* A property tree with std::string for key and data, and default
* comparison.
*/
typedef basic_ptree<std::string, std::string> ptree;
We can see that ptree uses std::string internally for both its keys and values. This implies that ptree's preferred data format is std::string.
As such the recommendation is to use:
std::string segmentCode = dataTree.get<std::string>("segmentCode");
This is more efficient than your workaround as the string should only be being copied once (from the ptree). While strdup
will create yet another copy and then require an explicit call later to free
.
-
Now as to where that access violation is coming from...
If we have a look at the basic_tree::get<Type>()
method:
/** Shorthand for get_child(path).get_value\<Type\>(). */
template<class Type>
Type get(const path_type &path) const;
we see this calls through to 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;
Notice the mention of type translation and a default translator.
Further down the call stack we find the point of access violation is actually within the translation process and can be found in 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;
}
}
Using streams in this way is a common technique for generically converting between types. Especially when one of the types being converted to/from is a string.
Problem here is that a get<char*>
defines the storage type (where we are putting the value) to be a char pointer. From ptree's perspective this is considered to be a complete type that can hold a value, while the translating stream considers this as a pointer to an area of memory that can be written to.
This is the equivalent of:
std::istringstream iss("value");
char * p; // uninitialized pointer
iss >> p; // write to some random memory location
and is why an access violation occurs.
Again the Type being passed to get<Type>
is expected to be able to hold a complete value.