Skip to content
This repository has been archived by the owner on Dec 16, 2019. It is now read-only.

Commit

Permalink
CBash handles out of memory conditions more gracefully
Browse files Browse the repository at this point in the history
  It now tries to clear up some memory before failing
Exported new function, UnloadAllCollections
UnloadMod no longer calls RaiseCallback if there wasn't an error
NonNullStringRecord no longer inherits from StringRecord
  Saves ~9MB by avoiding the needless vtable
NonNullStringRecord no longer writes the null terminator
Min loading Oblivion.esm now uses ~90MB less ram, but full loading uses ~20MB more ram
  Ob::REFRRecord accesses will be (trivially?) slower due to an extra pointer
  performance benching needed
  • Loading branch information
waruddar committed Jun 2, 2011
1 parent 210f9ef commit 8aad423
Show file tree
Hide file tree
Showing 13 changed files with 973 additions and 586 deletions.
Binary file modified CBash.suo
Binary file not shown.
70 changes: 68 additions & 2 deletions CBash/CBash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ GPL License and Copyright Notice ============================================
#include "CBash.h"
#include <vector>
#include <stdarg.h>
#include <new.h>
//#include "mmgr.h"

static std::vector<Collection *> Collections;
Expand Down Expand Up @@ -180,9 +181,49 @@ void AllowRaising(void (*_RaiseCallback)())
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//Collection action functions
int handle_program_memory_depletion(size_t size)
{
static int retrying = 0;

if(retrying == 0)
{
printer("Warning - Allocation of %u bytes failed. Attempting to free memory and continue.\n", size);
//try to free up some memory
if(UnloadAllCollections() == 0)
{
//see if enough memory was freed
//flag the function so that if the new fails, it doesn't infi-loop
retrying = 1;
char *test = new char[size];
//if the code gets this far, there's enough memory
//so free the test, and retry the initial allocation
delete []test;
retrying = 0;
return 1;
}
}

printer("Error - Unable to allocate %u bytes. CBash will terminate.\n", size);
DeleteAllCollections();
throw std::bad_alloc();
return 0;
}

Collection * CreateCollection(STRING const ModsPath, const UINT32 CollectionType)
{
PROFILE_FUNC
try
{
_set_new_handler(handle_program_memory_depletion);
}
catch(std::exception &ex)
{
PRINT_EXCEPTION(ex);
}
catch(...)
{
PRINT_ERROR;
}

try
{
Expand Down Expand Up @@ -338,6 +379,30 @@ SINT32 UnloadCollection(Collection *CollectionID)
return -1;
}

SINT32 UnloadAllCollections()
{
PROFILE_FUNC

try
{
for(UINT32 p = 0; p < Collections.size(); ++p)
Collections[p]->Unload();
return 0;
}
catch(std::exception &ex)
{
PRINT_EXCEPTION(ex);
}
catch(...)
{
PRINT_ERROR;
}
printer("\n\n");
if(RaiseCallback != NULL)
RaiseCallback();
return -1;
}

SINT32 DeleteAllCollections()
{
PROFILE_FUNC
Expand Down Expand Up @@ -426,6 +491,7 @@ SINT32 UnloadMod(Collection *CollectionID, ModFile *ModID)
//ValidatePointer(ModID);
RecordUnloader unloader;
ModID->VisitAllRecords(unloader);
return 0;
}
catch(std::exception &ex)
{
Expand All @@ -438,7 +504,7 @@ SINT32 UnloadMod(Collection *CollectionID, ModFile *ModID)
printer("\n\n");
if(RaiseCallback != NULL)
RaiseCallback();
return 0;
return -1;
}

SINT32 CleanModMasters(Collection *CollectionID, ModFile *ModID)
Expand Down Expand Up @@ -781,7 +847,7 @@ SINT32 GetModLoadOrderByID(Collection *CollectionID, ModFile *ModID)
printer("\n\n");
if(RaiseCallback != NULL)
RaiseCallback();
return -1;
return -2;
}

STRING GetLongIDName(Collection *CollectionID, ModFile *ModID, const UINT8 ModIndex)
Expand Down
1 change: 1 addition & 0 deletions CBash/CBash.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ EXPORT_FUNC Collection * CreateCollection(STRING const ModsPath, const UINT32 Co
EXPORT_FUNC SINT32 DeleteCollection(Collection *CollectionID);
EXPORT_FUNC SINT32 LoadCollection(Collection *CollectionID);
EXPORT_FUNC SINT32 UnloadCollection(Collection *CollectionID);
EXPORT_FUNC SINT32 UnloadAllCollections();
EXPORT_FUNC SINT32 DeleteAllCollections();
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
Expand Down
78 changes: 73 additions & 5 deletions CBash/Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,8 @@ UINT32 ModFlags::GetFlags()
return flags;
}

StringRecord::StringRecord():value(NULL)
StringRecord::StringRecord():
value(NULL)
{
//
}
Expand All @@ -834,7 +835,7 @@ StringRecord::StringRecord(const STRING p):

StringRecord::~StringRecord()
{
Unload();
delete []value;
}

UINT32 StringRecord::GetSize() const
Expand Down Expand Up @@ -887,6 +888,7 @@ void StringRecord::ReqWrite(UINT32 _Type, FileWriter &writer)
writer.record_write_subrecord(_Type, &null, 1);
}
}

void StringRecord::Copy(const StringRecord &FieldValue)
{
Copy(FieldValue.value);
Expand Down Expand Up @@ -921,27 +923,43 @@ StringRecord& StringRecord::operator = (const StringRecord &rhs)
}

NonNullStringRecord::NonNullStringRecord():
StringRecord()
value(NULL)
{
//
}

NonNullStringRecord::NonNullStringRecord(const NonNullStringRecord &p):
StringRecord()
value(NULL)
{
Copy(p.value);
}

NonNullStringRecord::~NonNullStringRecord()
{
//
delete []value;
}

UINT32 NonNullStringRecord::GetSize() const
{
return (UINT32)strlen(value);
}

bool NonNullStringRecord::IsLoaded() const
{
return value != NULL;
}

void NonNullStringRecord::Load()
{
//
}

void NonNullStringRecord::Unload()
{
delete []value;
value = NULL;
}

bool NonNullStringRecord::Read(unsigned char *buffer, const UINT32 &subSize, UINT32 &curPos)
{
if(IsLoaded())
Expand All @@ -956,6 +974,56 @@ bool NonNullStringRecord::Read(unsigned char *buffer, const UINT32 &subSize, UIN
return true;
}

void NonNullStringRecord::Write(UINT32 _Type, FileWriter &writer)
{
if(value != NULL)
writer.record_write_subrecord(_Type, value, (UINT32)strlen(value));
}

void NonNullStringRecord::ReqWrite(UINT32 _Type, FileWriter &writer)
{
if(value != NULL)
writer.record_write_subrecord(_Type, value, (UINT32)strlen(value));
else
{
char null = 0x00;
writer.record_write_subrecord(_Type, &null, 1);
}
}

void NonNullStringRecord::Copy(const NonNullStringRecord &FieldValue)
{
Copy(FieldValue.value);
}

void NonNullStringRecord::Copy(STRING FieldValue)
{
Unload();
if(FieldValue != NULL)
{
UINT32 size = (UINT32)strlen(FieldValue) + 1;
value = new char[size];
strcpy_s(value, size, FieldValue);
}
}

bool NonNullStringRecord::equals(const NonNullStringRecord &other) const
{
return cmps(value, other.value) == 0;
}

bool NonNullStringRecord::equalsi(const NonNullStringRecord &other) const
{
return icmps(value, other.value) == 0;
}

NonNullStringRecord& NonNullStringRecord::operator = (const NonNullStringRecord &rhs)
{
if(this != &rhs)
Copy(rhs);
return *this;
}

UnorderedPackedStrings::UnorderedPackedStrings()
{
//
Expand Down
23 changes: 19 additions & 4 deletions CBash/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -593,15 +593,15 @@ class StringRecord
StringRecord();
StringRecord(const StringRecord &p);
StringRecord(const STRING p);
virtual ~StringRecord();
~StringRecord();

virtual UINT32 GetSize() const;
UINT32 GetSize() const;

bool IsLoaded() const;
void Load();
void Unload();

virtual bool Read(unsigned char *buffer, const UINT32 &subSize, UINT32 &curPos);
bool Read(unsigned char *buffer, const UINT32 &subSize, UINT32 &curPos);
void Write(UINT32 _Type, FileWriter &writer);
void ReqWrite(UINT32 _Type, FileWriter &writer);

Expand All @@ -613,16 +613,31 @@ class StringRecord
StringRecord& operator = (const StringRecord &rhs);
};

class NonNullStringRecord : public StringRecord
class NonNullStringRecord
{
public:
STRING value;

NonNullStringRecord();
NonNullStringRecord(const NonNullStringRecord &p);
~NonNullStringRecord();

UINT32 GetSize() const;

bool IsLoaded() const;
void Load();
void Unload();

bool Read(unsigned char *buffer, const UINT32 &subSize, UINT32 &curPos);
void Write(UINT32 _Type, FileWriter &writer);
void ReqWrite(UINT32 _Type, FileWriter &writer);

void Copy(const NonNullStringRecord &FieldValue);
void Copy(STRING FieldValue);

bool equals(const NonNullStringRecord &other) const;
bool equalsi(const NonNullStringRecord &other) const;
NonNullStringRecord& operator = (const NonNullStringRecord &rhs);
};

struct UnorderedPackedStrings
Expand Down
Loading

0 comments on commit 8aad423

Please sign in to comment.