Fix a pile of actual memory leaks

Originally committed to SVN as r4575.
This commit is contained in:
Thomas Goyne 2010-06-24 01:24:09 +00:00
parent cbf201ab86
commit 2b47f34e76
8 changed files with 80 additions and 88 deletions

View file

@ -21,6 +21,8 @@
#include "charset_ucd.h" #include "charset_ucd.h"
#ifndef LAGI_PRE #ifndef LAGI_PRE
#include <memory>
#include "../../universalchardet/nsCharSetProber.h" #include "../../universalchardet/nsCharSetProber.h"
#endif #endif
@ -31,8 +33,7 @@ namespace agi {
UCDetect::UCDetect(const std::string &file): nsUniversalDetector(NS_FILTER_ALL) { UCDetect::UCDetect(const std::string &file): nsUniversalDetector(NS_FILTER_ALL) {
{ {
std::ifstream *fp; std::auto_ptr<std::ifstream> fp(io::Open(file));
fp = io::Open(file);
while (!mDone && !fp->eof()) { while (!mDone && !fp->eof()) {
char buf[512]; char buf[512];

View file

@ -22,6 +22,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <algorithm>
#include <functional>
#include <memory> #include <memory>
#endif #endif
@ -40,99 +42,84 @@ std::auto_ptr<LogSink> log(new LogSink());
/// Keep this ordered the same as Severity /// Keep this ordered the same as Severity
const char *Severity_ID = "EAWID"; const char *Severity_ID = "EAWID";
SinkMessage::SinkMessage(const char *section, Severity severity, const char *file, SinkMessage::SinkMessage(const char *section, Severity severity,
const char *func, int line, agi_timeval tv): const char *file, const char *func, int line,
section(section), agi_timeval tv)
severity(severity), : section(section)
file(file), , severity(severity)
func(func), , file(file)
line(line), , func(func)
tv(tv) { , line(line)
, tv(tv)
, message(NULL)
, len(0)
{
} }
SinkMessage::~SinkMessage() { SinkMessage::~SinkMessage() {
///@todo Memory cleanup delete message;
} }
LogSink::LogSink(): emit(0) { LogSink::LogSink() {
sink = new Sink();
} }
LogSink::~LogSink() { LogSink::~LogSink() {
/// @todo This needs to flush all log data to disk on quit. /// @todo This needs to flush all log data to disk on quit.
if (emit) { agi::util::delete_clear(sink);
for (int i = emitters.size()-1; i >= 0; i--) {
delete emitters[i];
}
}
} }
void LogSink::log(SinkMessage *sm) { void LogSink::log(SinkMessage *sm) {
sink->push_back(sm); sink.push_back(sm);
if (emit) { std::for_each(
for (int i = emitters.size()-1; i >= 0; i--) { emitters.begin(),
emitters[i]->log(sm); emitters.end(),
} std::bind2nd(std::mem_fun(&Emitter::log), sm));
}
} }
void LogSink::Subscribe(Emitter *em) {
Emitter::~Emitter() { emitters.push_back(em);
} }
void LogSink::Unsubscribe(Emitter *em) {
Emitter::Emitter() { emitters.erase(std::remove(emitters.begin(), emitters.end(), em), emitters.end());
} }
int LogSink::Subscribe(Emitter &em) {
emitters.push_back(&em);
emit = 1;
/// @todo This won't work since removing it will cause the id's to change,
/// it's good enough while this is being written.
return emitters.size();
}
void LogSink::Unsubscribe(const int &id) {
emitters.erase((emitters.begin()-1)+id);
if (emitters.size() == 0)
emit = 0;
}
Message::Message(const char *section, Message::Message(const char *section,
Severity severity, Severity severity,
const char *file, const char *file,
const char *func, const char *func,
int line): int line)
len(1024) { : len(1024)
buf = new char[len]; , buf(new char[len])
msg = new std::ostrstream(buf, len); , msg(buf, len)
{
agi_timeval tv; agi_timeval tv;
util::time_log(tv); util::time_log(tv);
sm = new SinkMessage(section, severity, file, func, line, tv); sm = new SinkMessage(section, severity, file, func, line, tv);
} }
Message::~Message() { Message::~Message() {
sm->message = msg->str(); sm->message = msg.str();
sm->len = msg->pcount(); sm->len = msg.pcount();
agi::log::log->log(sm); agi::log::log->log(sm);
delete msg;
} }
Emitter::Emitter() {
}
Emitter::~Emitter() {
Disable();
}
void Emitter::Enable() { void Emitter::Enable() {
id = agi::log::log->Subscribe(*(this)); agi::log::log->Subscribe(this);
} }
void Emitter::Disable() { void Emitter::Disable() {
agi::log::log->Unsubscribe(id); agi::log::log->Unsubscribe(this);
} }

View file

@ -22,6 +22,7 @@
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <map> #include <map>
#include <memory>
#include "libaegisub/cajun/reader.h" #include "libaegisub/cajun/reader.h"
#include "libaegisub/cajun/writer.h" #include "libaegisub/cajun/writer.h"
@ -55,10 +56,10 @@ void Options::ConfigNext(std::istream& stream) {
} }
void Options::ConfigUser() { void Options::ConfigUser() {
std::istream *stream; std::auto_ptr<std::istream> stream;
try { try {
stream = agi::io::Open(config_file); stream.reset(agi::io::Open(config_file));
} catch (const acs::AcsNotFound&) { } catch (const acs::AcsNotFound&) {
return; return;
} }
@ -66,7 +67,6 @@ void Options::ConfigUser() {
/// @todo Handle other errors such as parsing and notifying the user. /// @todo Handle other errors such as parsing and notifying the user.
LoadConfig(*stream); LoadConfig(*stream);
config_loaded = true; config_loaded = true;
delete stream;
} }

View file

@ -77,11 +77,11 @@ struct SinkMessage {
/// @param file File name /// @param file File name
/// @param func Function name /// @param func Function name
/// @param line Source line /// @param line Source line
/// @param tv Log time /// @param tv Log time
SinkMessage(const char *section, Severity severity, const char *file, SinkMessage(const char *section, Severity severity, const char *file,
const char *func, int line, agi_timeval tv); const char *func, int line, agi_timeval tv);
// Destructor /// Destructor
~SinkMessage(); ~SinkMessage();
const char *section; ///< Section info eg "video/open" "video/seek" etc const char *section; ///< Section info eg "video/open" "video/seek" etc
@ -105,14 +105,11 @@ class LogSink {
int64_t size; int64_t size;
/// Log sink /// Log sink
Sink *sink; Sink sink;
/// List of function pointers to emitters /// List of function pointers to emitters
std::vector<Emitter*> emitters; std::vector<Emitter*> emitters;
/// Whether to enable emitters
bool emit;
public: public:
/// Constructor /// Constructor
LogSink(); LogSink();
@ -124,24 +121,20 @@ public:
void log(SinkMessage *sm); void log(SinkMessage *sm);
/// @brief Subscribe an emitter. /// @brief Subscribe an emitter.
/// @param Function pointer to an emitter /// @param em Emitter to add
/// @return ID for this Emitter void Subscribe(Emitter *em);
int Subscribe(Emitter &em);
/// @brief Unsubscribe an emitter. /// @brief Unsubscribe an emitter.
/// @param id ID to remove. /// @param em Emitter to remove
void Unsubscribe(const int &id); void Unsubscribe(Emitter *em);
/// @brief @get the complete (current) log. /// @brief @get the complete (current) log.
/// @return Const pointer to internal sink. /// @return Const pointer to internal sink.
const Sink* GetSink() { return sink; } const Sink* GetSink() { return &sink; }
}; };
/// An emitter to produce human readable output for a log sink. /// An emitter to produce human readable output for a log sink.
class Emitter { class Emitter {
/// ID for this emitter
int id;
public: public:
/// Constructor /// Constructor
Emitter(); Emitter();
@ -162,9 +155,9 @@ public:
/// Generates a message and submits it to the log sink. /// Generates a message and submits it to the log sink.
class Message { class Message {
char *buf;
const int len; const int len;
std::ostrstream *msg; char *buf;
std::ostrstream msg;
SinkMessage *sm; SinkMessage *sm;
public: public:
@ -174,7 +167,7 @@ public:
const char *func, const char *func,
int line); int line);
~Message(); ~Message();
std::ostream& stream() { return *(msg); } std::ostream& stream() { return msg; }
}; };

View file

@ -34,5 +34,17 @@ namespace agi {
void Rename(const std::string& from, const std::string& to); void Rename(const std::string& from, const std::string& to);
void time_log(agi_timeval &tv); void time_log(agi_timeval &tv);
struct delete_ptr {
template<class T>
void operator()(T* ptr) const {
delete ptr;
}
};
template<class T>
void delete_clear(T& container) {
std::for_each(container.begin(), container.end(), delete_ptr());
container.clear();
}
} // namespace util } // namespace util
} // namespace agi } // namespace agi

View file

@ -37,7 +37,7 @@ void EmitSTDOUT::log(SinkMessage *sm) {
// tmtime.tm_mon, // tmtime.tm_mon,
// tmtime.tm_mday, // tmtime.tm_mday,
printf("%c %02d:%02d:%02d %ld <%-25s> [%s:%s:%d] %s\n", printf("%c %02d:%02d:%02d %ld <%-25s> [%s:%s:%d] %.*s\n",
Severity_ID[sm->severity], Severity_ID[sm->severity],
tmtime.tm_hour, tmtime.tm_hour,
tmtime.tm_min, tmtime.tm_min,
@ -47,8 +47,8 @@ void EmitSTDOUT::log(SinkMessage *sm) {
sm->file, sm->file,
sm->func, sm->func,
sm->line, sm->line,
strndup(sm->message, sm->len,
sm->len)); sm->message);
} }
} // namespace log } // namespace log

View file

@ -30,15 +30,15 @@ namespace agi {
namespace log { namespace log {
void EmitSTDOUT::log(SinkMessage *sm) { void EmitSTDOUT::log(SinkMessage *sm) {
/*
tm tmtime; tm tmtime;
localtime_r(&sm->tv.tv_sec, &tmtime); time_t time = sm->tv.tv_sec;
localtime_s(&tmtime, &time);
// tmtime.tm_year+1900, // tmtime.tm_year+1900,
// tmtime.tm_mon, // tmtime.tm_mon,
// tmtime.tm_mday, // tmtime.tm_mday,
printf("%c %02d:%02d:%02d %ld <%-25s> [%s:%s:%d] %s\n", printf("%c %02d:%02d:%02d %ld <%-25s> [%s:%s:%d] %.*s\n",
Severity_ID[sm->severity], Severity_ID[sm->severity],
tmtime.tm_hour, tmtime.tm_hour,
tmtime.tm_min, tmtime.tm_min,
@ -48,9 +48,8 @@ void EmitSTDOUT::log(SinkMessage *sm) {
sm->file, sm->file,
sm->func, sm->func,
sm->line, sm->line,
strndup(sm->message, sm->len,
sm->len)); sm->message);
*/
} }
} // namespace log } // namespace log
} // namespace agi } // namespace agi

View file

@ -144,8 +144,8 @@ void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName) {
/// ///
bool AegisubApp::OnInit() { bool AegisubApp::OnInit() {
#ifdef _DEBUG #ifdef _DEBUG
agi::log::EmitSTDOUT *emit_stdout = new agi::log::EmitSTDOUT(); agi::log::EmitSTDOUT emit_stdout;
emit_stdout->Enable(); emit_stdout.Enable();
#endif #endif
// App name (yeah, this is a little weird to get rid of an odd warning) // App name (yeah, this is a little weird to get rid of an odd warning)