fix to memory leak in wesnothd

This commit is contained in:
David White 2009-10-08 19:38:22 +00:00
parent 36fa12d2d9
commit a5ba61e6ed
3 changed files with 27 additions and 22 deletions

View file

@ -252,7 +252,7 @@ void game::update_side_data() {
if (!lg::debug.dont_log(log_server)) {
for (simple_wml::node::child_list::const_iterator side = level_sides.begin();
side != level_sides.end(); ++side)
DBG_GAME << "[side]\n" << (**side).output() << "[/side]\n";
DBG_GAME << "[side]\n" << simple_wml::node_to_string(**side) << "[/side]\n";
}
// For each user:
// * Find the username.
@ -763,7 +763,7 @@ bool game::process_turn(simple_wml::document& data, const player_map::const_iter
if (!is_current_player(user->first)
&& !is_legal_command(**command, player)) {
LOG_GAME << "ILLEGAL COMMAND in game: " << id_ << " ((("
<< (**command).output() << ")))\n";
<< simple_wml::node_to_string(**command) << ")))\n";
std::stringstream msg;
msg << "Removing illegal command '" << (**command).first_child().to_string()
<< "' from: " << user->second.name()
@ -942,7 +942,6 @@ bool game::add_player(const network::connection player, bool observer) {
user->second.set_status((observer || became_observer) ? player::OBSERVING : player::PLAYING);
DBG_GAME << debug_player_info();
// Send the user the game data.
//std::cerr << "SENDING LEVEL {{{" << level_.output() << "}}}\n";
if (!wesnothd::send_to_one(level_, player)) return false;
if(started_) {
@ -1224,7 +1223,7 @@ void game::save_replay() {
const simple_wml::node::child_list& turn_list = (*i)->root().children("turn");
for (simple_wml::node::child_list::const_iterator turn = turn_list.begin();
turn != turn_list.end(); ++turn) {
replay_commands += (*turn)->output();
replay_commands += simple_wml::node_to_string(**turn);
}
delete *i;
}

View file

@ -691,11 +691,13 @@ void node::shift_buffers(ptrdiff_t offset)
}
}
void node::output(char*& buf)
void node::output(char*& buf, CACHE_STATUS cache_status)
{
if(output_cache_.empty() == false) {
memcpy(buf, output_cache_.begin(), output_cache_.size());
shift_buffers(buf - output_cache_.begin());
if(cache_status == REFRESH_CACHE) {
shift_buffers(buf - output_cache_.begin());
}
buf += output_cache_.size();
return;
}
@ -726,7 +728,7 @@ void node::output(char*& buf)
buf += attr.size();
*buf++ = ']';
*buf++ = '\n';
children_[i->child_map_index].second[i->child_list_index]->output(buf);
children_[i->child_map_index].second[i->child_list_index]->output(buf, cache_status);
*buf++ = '[';
*buf++ = '/';
memcpy(buf, attr.begin(), attr.size());
@ -735,20 +737,21 @@ void node::output(char*& buf)
*buf++ = '\n';
}
output_cache_ = string_span(begin, buf - begin);
if(cache_status == REFRESH_CACHE) {
output_cache_ = string_span(begin, buf - begin);
}
}
const char* node::output() {
const char* out;
const int buf_size = output_size() + 1;
char* buf = new char[buf_size];
out = buf;
output(buf);
*buf++ = 0;
assert(buf == out + buf_size);
return out;
std::string node_to_string(const node& n)
{
//calling output with status=DO_NOT_MODIFY_CACHE really doesn't modify the
//node, so we can do it safely
node& mutable_node = const_cast<node&>(n);
std::vector<char> v(mutable_node.output_size());
char* ptr = &v[0];
mutable_node.output(ptr, node::DO_NOT_MODIFY_CACHE);
assert(ptr == &v[0] + v.size());
return std::string(v.begin(), v.end());
}
void node::copy_into(node& n) const
@ -1004,7 +1007,7 @@ const char* document::output()
buffers_.push_back(buf);
output_ = buf;
root_->output(buf);
root_->output(buf, node::REFRESH_CACHE);
*buf++ = 0;
assert(buf == output_ + buf_size);

View file

@ -140,9 +140,10 @@ public:
bool is_dirty() const { return output_cache_.is_null(); }
enum CACHE_STATUS { REFRESH_CACHE, DO_NOT_MODIFY_CACHE };
int output_size() const;
void output(char*& buf);
const char* output();
void output(char*& buf, CACHE_STATUS status=DO_NOT_MODIFY_CACHE);
void copy_into(node& n) const;
@ -203,6 +204,8 @@ private:
string_span output_cache_;
};
std::string node_to_string(const node& n);
enum INIT_BUFFER_CONTROL { INIT_TAKE_OWNERSHIP };
enum INIT_STATE { INIT_COMPRESSED, INIT_STATIC };