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

View file

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

View file

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

View file

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

View file

@ -37,7 +37,7 @@ void EmitSTDOUT::log(SinkMessage *sm) {
// tmtime.tm_mon,
// 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],
tmtime.tm_hour,
tmtime.tm_min,
@ -47,8 +47,8 @@ void EmitSTDOUT::log(SinkMessage *sm) {
sm->file,
sm->func,
sm->line,
strndup(sm->message,
sm->len));
sm->len,
sm->message);
}
} // namespace log

View file

@ -30,15 +30,15 @@ namespace agi {
namespace log {
void EmitSTDOUT::log(SinkMessage *sm) {
/*
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_mon,
// 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],
tmtime.tm_hour,
tmtime.tm_min,
@ -48,9 +48,8 @@ void EmitSTDOUT::log(SinkMessage *sm) {
sm->file,
sm->func,
sm->line,
strndup(sm->message,
sm->len));
*/
sm->len,
sm->message);
}
} // namespace log
} // namespace agi

View file

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