Fixed a few memory leaks

This commit is contained in:
Zane U. Ji 2012-08-27 20:25:08 +08:00
parent 0e3bfd65e5
commit 8df6cd065b
9 changed files with 166 additions and 29 deletions

61
src/threadreaper.cpp Normal file
View File

@ -0,0 +1,61 @@
/*
* Copyright 2012 Zane U. Ji.
*
* This file is part of Xml Copy Editor.
*
* Xml Copy Editor is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* Xml Copy Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Xml Copy Editor; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "threadreaper.h"
extern wxCriticalSection xmlcopyeditorCriticalSection;
ThreadReaper::ThreadReaper ()
{
}
ThreadReaper::~ThreadReaper ()
{
//wxCriticalSectionLocker lock ( xmlcopyeditorCriticalSection );
std::vector<boost::shared_ptr<wxThread> >::iterator itr;
for ( itr = mList.begin(); itr != mList.end(); itr++)
{
(**itr).Kill();
}
}
ThreadReaper &ThreadReaper::get()
{
static ThreadReaper reaper;
return reaper;
}
void ThreadReaper::add ( wxThread *thread )
{
// Make sure everything is valid when wxPostMessage is called
// and protect mList
wxCriticalSectionLocker lock ( xmlcopyeditorCriticalSection );
mList.push_back ( boost::shared_ptr<wxThread> ( thread ) );
std::vector<boost::shared_ptr<wxThread> >::iterator itr;
for ( itr = mList.begin(); itr != mList.end(); )
{
if ( (**itr).IsAlive() )
itr++;
else
itr = mList.erase ( itr );
}
}

42
src/threadreaper.h Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright 2012 Zane U. Ji.
*
* This file is part of Xml Copy Editor.
*
* Xml Copy Editor is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* Xml Copy Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Xml Copy Editor; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef THREADREAPER_H_
#define THREADREAPER_H_
#include <wx/wx.h>
#include <vector>
#include <boost/shared_ptr.hpp>
class ThreadReaper
{
protected:
ThreadReaper();
virtual ~ThreadReaper();
public:
static ThreadReaper &get();
void add ( wxThread *thread );
protected:
std::vector<boost::shared_ptr<wxThread> > mList;
};
#endif /* THREADREAPER_H_ */

View File

@ -4,7 +4,9 @@
#include "wrapxerces.h" #include "wrapxerces.h"
#include <stdexcept> #include <stdexcept>
#include <memory> #include <memory>
#include "threadreaper.h"
extern wxCriticalSection xmlcopyeditorCriticalSection;
DEFINE_EVENT_TYPE(wxEVT_COMMAND_VALIDATION_COMPLETED); DEFINE_EVENT_TYPE(wxEVT_COMMAND_VALIDATION_COMPLETED);
@ -15,6 +17,7 @@ ValidationThread::ValidationThread (
const char *catalogPath, const char *catalogPath,
const char *catalogUtilityPath ) const char *catalogUtilityPath )
: wxThread ( wxTHREAD_JOINABLE ) : wxThread ( wxTHREAD_JOINABLE )
, mStopping ( false )
{ {
if ( buffer == NULL ) if ( buffer == NULL )
{ {
@ -35,25 +38,22 @@ void *ValidationThread::Entry()
myCatalogPath, myCatalogPath,
myCatalogUtilityPath ) ); myCatalogUtilityPath ) );
if ( TestDestroy() )
{ {
//wxCriticalSectionLocker locker ( xmlcopyeditorCriticalSection ); return NULL;
if ( TestDestroy() )
{
return NULL;
}
} }
myIsSucceeded = validator->validateMemory ( myIsSucceeded = validator->validateMemory (
myBuffer.c_str(), myBuffer.c_str(),
myBuffer.size(),
mySystem.c_str(), mySystem.c_str(),
myBuffer.size() ); this );
if ( TestDestroy() ) if ( TestDestroy() )
{ {
return NULL; return NULL;
} }
extern wxCriticalSection xmlcopyeditorCriticalSection;
wxCriticalSectionLocker locker ( xmlcopyeditorCriticalSection ); wxCriticalSectionLocker locker ( xmlcopyeditorCriticalSection );
if ( myIsSucceeded ) if ( myIsSucceeded )
@ -67,8 +67,18 @@ void *ValidationThread::Entry()
myMessage = validator->getLastError(); myMessage = validator->getLastError();
} }
wxCommandEvent event ( wxEVT_COMMAND_VALIDATION_COMPLETED ); if ( !TestDestroy() )
wxPostEvent ( myEventHandler, event ); {
wxCommandEvent event ( wxEVT_COMMAND_VALIDATION_COMPLETED );
wxPostEvent ( myEventHandler, event );
}
return NULL; return NULL;
} }
void ValidationThread::PendingDelete ()
{
Cancel();
ThreadReaper::get().add ( this );
}

View File

@ -22,12 +22,21 @@ public:
bool isSucceeded () { return myIsSucceeded; } bool isSucceeded () { return myIsSucceeded; }
const std::pair<int, int> &getPosition() { return myPosition; } const std::pair<int, int> &getPosition() { return myPosition; }
const wxString &getMessage() { return myMessage; } const wxString &getMessage() { return myMessage; }
private:
void PendingDelete();
// Since we can't call wxThread::m_internal->Cancel(), the original
// TestDestroy() is useless. Here is the work around.
virtual void Cancel() { mStopping = true; }
virtual bool TestDestroy() { return mStopping || wxThread::TestDestroy(); }
protected:
wxEvtHandler *myEventHandler; wxEvtHandler *myEventHandler;
std::string myBuffer, mySystem, myCatalogPath, myCatalogUtilityPath; std::string myBuffer, mySystem, myCatalogPath, myCatalogUtilityPath;
bool myIsSucceeded; bool myIsSucceeded;
std::pair<int, int> myPosition; std::pair<int, int> myPosition;
wxString myMessage; wxString myMessage;
bool mStopping;
}; };
#endif #endif

View File

@ -113,8 +113,9 @@ bool WrapXerces::validate ( const std::string& fileName )
// tbd: cache grammar // tbd: cache grammar
bool WrapXerces::validateMemory ( bool WrapXerces::validateMemory (
const char *buffer, const char *buffer,
size_t len,
const char *system, const char *system,
unsigned len ) wxThread *thread /*= NULL*/ )
{ {
std::auto_ptr<SAX2XMLReader> parser ( XMLReaderFactory::createXMLReader() ); std::auto_ptr<SAX2XMLReader> parser ( XMLReaderFactory::createXMLReader() );
@ -125,7 +126,7 @@ bool WrapXerces::validateMemory (
//parser->setFeature ( XMLUni::fgXercesSchemaFullChecking, true ); //parser->setFeature ( XMLUni::fgXercesSchemaFullChecking, true );
parser->setFeature ( XMLUni::fgXercesValidationErrorAsFatal, true ); parser->setFeature ( XMLUni::fgXercesValidationErrorAsFatal, true );
parser->setFeature ( XMLUni::fgXercesLoadExternalDTD, true ); parser->setFeature ( XMLUni::fgXercesLoadExternalDTD, true );
DefaultHandler handler; DefaultHandler handler;
MySAX2Handler mySAX2Handler; MySAX2Handler mySAX2Handler;
parser->setContentHandler ( &handler ); parser->setContentHandler ( &handler );
@ -138,7 +139,17 @@ bool WrapXerces::validateMemory (
try try
{ {
parser->parse ( source ); if ( thread == NULL )
{
parser->parse ( source );
}
else if ( !thread->TestDestroy() )
{
XMLPScanToken token;
if ( parser->parseFirst ( source, token ) )
while ( (!thread->TestDestroy()) && parser->parseNext ( token ) )
continue;
}
} }
catch ( XMLException& e ) catch ( XMLException& e )
{ {

View File

@ -41,7 +41,8 @@ class WrapXerces
std::string catalogUtilityPath = "" ); std::string catalogUtilityPath = "" );
~WrapXerces(); ~WrapXerces();
bool validate ( const std::string& fileName ); bool validate ( const std::string& fileName );
bool validateMemory ( const char *buffer, const char *system, unsigned len ); bool validateMemory ( const char *buffer, size_t len,
const char *system, wxThread *thread = NULL );
const wxString &getLastError(); const wxString &getLastError();
std::pair<int, int> getErrorPosition(); std::pair<int, int> getErrorPosition();
static wxString toString ( const XMLCh *str ); static wxString toString ( const XMLCh *str );

View File

@ -3123,7 +3123,7 @@ bool MyFrame::openFile ( wxString& fileName, bool largeFile )
statusProgress ( wxEmptyString ); statusProgress ( wxEmptyString );
char *iconvBuffer = 0; wxCharBuffer iconvBuffer;
size_t iconvBufferLen = 0; size_t iconvBufferLen = 0;
char *finalBuffer; char *finalBuffer;
@ -3230,21 +3230,21 @@ bool MyFrame::openFile ( wxString& fileName, bool largeFile )
iconvLenMultiplier = 1; iconvLenMultiplier = 1;
} }
size_t nconv;
char *buffer;
size_t iconvBufferLeft, docBufferLeft; size_t iconvBufferLeft, docBufferLeft;
iconvBufferLen = iconvBufferLeft = (docBufferLen - nBOM) * iconvLenMultiplier + 1; iconvBufferLen = iconvBufferLeft = (docBufferLen - nBOM) * iconvLenMultiplier + 1;
docBufferLeft = docBufferLen; docBufferLeft = docBufferLen;
iconvBuffer = new char[iconvBufferLen]; iconvBuffer.extend ( iconvBufferLen );
finalBuffer = iconvBuffer; // iconvBuffer will be incremented by iconv finalBuffer = buffer = iconvBuffer.data(); // buffer will be incremented by iconv
size_t nconv;
nconv = reinterpret_cast < universal_iconv & > ( iconv ) ( nconv = reinterpret_cast < universal_iconv & > ( iconv ) (
cd, cd,
&docBuffer, &docBuffer,
&docBufferLeft, &docBufferLeft,
&iconvBuffer, &buffer,
&iconvBufferLeft ); &iconvBufferLeft );
*iconvBuffer = '\0'; *buffer = '\0';
iconv_close ( cd ); iconv_close ( cd );
@ -3255,7 +3255,6 @@ bool MyFrame::openFile ( wxString& fileName, bool largeFile )
fileName.c_str(), fileName.c_str(),
wideEncoding.c_str() ); wideEncoding.c_str() );
messagePane ( message, CONST_STOP ); messagePane ( message, CONST_STOP );
delete[] finalBuffer;
delete binaryfile; //delete memorymap; delete binaryfile; //delete memorymap;
return false; return false;
} }

View File

@ -138,8 +138,7 @@ XmlCtrl::~XmlCtrl()
if ( validationThread != NULL ) if ( validationThread != NULL )
{ {
validationThread->Kill(); validationThread->PendingDelete();
delete validationThread;
} }
} }

View File

@ -299,6 +299,7 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
PromptGeneratorData *d; PromptGeneratorData *d;
d = ( PromptGeneratorData * ) p; // arg is set to user data in c'tor d = ( PromptGeneratorData * ) p; // arg is set to user data in c'tor
int ret;
std::string buffer; std::string buffer;
// auxPath req'd? // auxPath req'd?
@ -307,15 +308,17 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
ReadFile::run ( d->auxPath, buffer ); ReadFile::run ( d->auxPath, buffer );
if ( buffer.empty() ) if ( buffer.empty() )
{ {
return false; return XML_STATUS_ERROR;
} }
std::string encoding = XmlEncodingHandler::get ( buffer ); std::string encoding = XmlEncodingHandler::get ( buffer );
XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() ); XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() );
if ( !dtdParser ) if ( !dtdParser )
return false; return XML_STATUS_ERROR;
XML_SetBase ( dtdParser, d->auxPath.c_str() ); XML_SetBase ( dtdParser, d->auxPath.c_str() );
return XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true ); ret = XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true );
XML_ParserFree ( dtdParser );
return ret;
} }
std::string stdPublicId; std::string stdPublicId;
@ -358,7 +361,7 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
std::string encoding = XmlEncodingHandler::get ( buffer ); std::string encoding = XmlEncodingHandler::get ( buffer );
XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() ); XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() );
if ( !dtdParser ) if ( !dtdParser )
return false; return XML_STATUS_ERROR;
wxString wideName, wideDir; wxString wideName, wideDir;
wideName = wxString ( stdSystemId.c_str(), wxConvUTF8, stdSystemId.size() ); wideName = wxString ( stdSystemId.c_str(), wxConvUTF8, stdSystemId.size() );
@ -366,7 +369,9 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
wideDir = fn.GetPath(); wideDir = fn.GetPath();
XML_SetBase ( dtdParser, wideName.mb_str ( wxConvUTF8 ) ); XML_SetBase ( dtdParser, wideName.mb_str ( wxConvUTF8 ) );
return XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true ); ret = XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true );
XML_ParserFree ( dtdParser );
return ret;
} }
void XMLCALL XmlPromptGenerator::entitydeclhandler ( void XMLCALL XmlPromptGenerator::entitydeclhandler (