Add MemoryDump class in base library to create mini-memory dumps on win32 platform.

This commit is contained in:
David Capello 2011-10-29 12:30:49 -03:00
parent cfd74c79bd
commit f767c06761
7 changed files with 188 additions and 21 deletions

View File

@ -189,12 +189,9 @@ if(WIN32)
shlwapi
psapi
wininet
dbghelp
)
if(MSVC AND ENABLE_MEMLEAK)
list(APPEND PLATFORM_LIBS dbghelp)
endif()
add_definitions(-D_WIN32_WINNT=0x0500)
endif(WIN32)

View File

@ -7,6 +7,7 @@ add_library(base-lib
exception.cpp
mem_utils.cpp
memory.cpp
memory_dump.cpp
mutex.cpp
path.cpp
serialization.cpp

34
src/base/memory_dump.cpp Normal file
View File

@ -0,0 +1,34 @@
// ASE base library
// Copyright (C) 2001-2011 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#include "config.h"
#include "base/memory_dump.h"
#ifdef WIN32
#include "base/memory_dump_win32.h"
#else
#include "base/memory_dump_none.h"
#endif
namespace base {
MemoryDump::MemoryDump()
: m_impl(new MemoryDumpImpl)
{
}
MemoryDump::~MemoryDump()
{
delete m_impl;
}
void MemoryDump::setFileName(const std::string& fileName)
{
m_impl->setFileName(fileName);
}
} // namespace base

28
src/base/memory_dump.h Normal file
View File

@ -0,0 +1,28 @@
// ASE base library
// Copyright (C) 2001-2011 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef BASE_MEMORY_DUMP_H_INCLUDED
#define BASE_MEMORY_DUMP_H_INCLUDED
#include <string>
namespace base {
class MemoryDump {
public:
MemoryDump();
~MemoryDump();
void setFileName(const std::string& fileName);
private:
class MemoryDumpImpl;
MemoryDumpImpl* m_impl;
};
} // namespace base
#endif // BASE_MEMORY_DUMP_H_INCLUDED

View File

@ -0,0 +1,26 @@
// ASE base library
// Copyright (C) 2001-2011 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef BASE_MEMORY_DUMP_NONE_H_INCLUDED
#define BASE_MEMORY_DUMP_NONE_H_INCLUDED
class base::MemoryDump::MemoryDumpImpl
{
public:
MemoryDumpImpl() {
// Do nothing
}
~MemoryDumpImpl() {
// Do nothing
}
void setFileName(const std::string& fileName) {
// Do nothing
}
};
#endif // BASE_MEMORY_DUMP_NONE_H_INCLUDED

View File

@ -0,0 +1,73 @@
// ASE base library
// Copyright (C) 2001-2011 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef BASE_MEMORY_DUMP_WIN32_H_INCLUDED
#define BASE_MEMORY_DUMP_WIN32_H_INCLUDED
#ifdef WIN32
#include <windows.h>
#include <dbghelp.h>
#endif
static std::string memoryDumpFile;
class base::MemoryDump::MemoryDumpImpl
{
public:
MemoryDumpImpl() {
memoryDumpFile = "memory.dmp";
::SetUnhandledExceptionFilter(MemoryDumpImpl::unhandledException);
}
~MemoryDumpImpl() {
::SetUnhandledExceptionFilter(NULL);
}
void setFileName(const std::string& fileName) {
memoryDumpFile = fileName;
}
static LONG WINAPI unhandledException(_EXCEPTION_POINTERS* exceptionPointers) {
MemoryDumpImpl::createMemoryDump(exceptionPointers);
return EXCEPTION_EXECUTE_HANDLER;
}
private:
class MemoryDumpFile {
public:
MemoryDumpFile() {
m_handle = ::CreateFile(memoryDumpFile.c_str(),
GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
}
~MemoryDumpFile() {
::CloseHandle(m_handle);
}
HANDLE handle() { return m_handle; }
private:
HANDLE m_handle;
};
static void createMemoryDump(_EXCEPTION_POINTERS* exceptionPointers) {
MemoryDumpFile file;
MINIDUMP_EXCEPTION_INFORMATION ei;
ei.ThreadId = GetCurrentThreadId();
ei.ExceptionPointers = exceptionPointers;
ei.ClientPointers = FALSE;
::MiniDumpWriteDump(::GetCurrentProcess(),
::GetCurrentProcessId(),
file.handle(),
MiniDumpNormal,
(exceptionPointers ? &ei: NULL),
NULL,
NULL);
}
};
#endif // BASE_MEMORY_DUMP_WIN32_H_INCLUDED

View File

@ -20,11 +20,13 @@
#include <allegro.h>
#include "app.h"
#include "base/exception.h"
#include "base/memory.h"
#include "app.h"
#include "base/memory_dump.h"
#include "console.h"
#include "loadpng.h"
#include "resource_finder.h"
#ifdef WIN32
#include <winalleg.h>
@ -68,6 +70,18 @@ public:
}
};
static bool get_memory_dump_filename(std::string& filename)
{
#ifdef WIN32
ResourceFinder rf;
rf.findInBinDir("aseprite-memory.dmp");
filename = rf.first();
return true;
#else
return false;
#endif
}
// ASE entry point
int main(int argc, char* argv[])
{
@ -75,28 +89,22 @@ int main(int argc, char* argv[])
CoInitialize(NULL);
#endif
int status = 1; // 1 = error
base::MemoryDump memoryDump;
Allegro allegro;
try {
#ifdef MEMLEAK
MemLeak memleak;
MemLeak memleak;
#endif
Jinete jinete;
App app(argc, argv);
Jinete jinete;
App app(argc, argv);
status = app.run();
// Change the name of the memory dump file
{
std::string filename;
if (get_memory_dump_filename(filename))
memoryDump.setFileName(filename);
}
catch (std::exception& e) {
allegro_message("%s", e.what());
}
#ifndef DEBUGMODE
catch (...) {
allegro_message("Uncaught exception");
}
#endif
return status;
return app.run();
}
END_OF_MAIN();