00001 #include "ReVolt.h"
00002 #include "Main.h"
00003
00004
00005 size_t DBG_AllocatedRAM = 0;
00006 size_t DBG_NAllocations = 0;
00007 char *DBG_LogFile = NULL;
00008
00009
00010 static MEMSTORE *MemStoreHead = NULL;
00011 static char ErrorMessage[1024];
00012 static size_t MaxAllocatedRAM = 0;
00013 static bool AlreadyWarned = FALSE;
00014 static bool AlreadyAsserted = FALSE;
00015 bool TellChris = FALSE;
00016
00017 bool AddMemStore(void);
00018 void DeleteMemStore(MEMSTORE *memStore);
00019 MEMSTORE *NextMemStore(MEMSTORE *memStore);
00020 void WriteLogEntry(char *s);
00021 void InitLogFile();
00022 void Error(char *mod, char *func, char *mess, long errno);
00023
00024
00026
00027
00028
00030
00031 bool AddMemStore()
00032 {
00033 MEMSTORE *oldHead;
00034
00035 oldHead = MemStoreHead;
00036
00037
00038 MemStoreHead = (MEMSTORE *)ReleaseMalloc(sizeof(MEMSTORE));
00039 if (MemStoreHead == NULL) {
00040 wsprintf(ErrorMessage, "Could not Allocate RAM for memory list");
00041 Box("Error", ErrorMessage, MB_OK | MB_ICONERROR);
00042 return FALSE;
00043 }
00044
00045 MemStoreHead->Next = oldHead;
00046 MemStoreHead->Prev = NULL;
00047 if (oldHead != NULL) {
00048 oldHead->Prev = MemStoreHead;
00049 }
00050 return TRUE;
00051 }
00052
00054
00055
00056
00058
00059 void DeleteMemStore(MEMSTORE *memStore) {
00060
00061 if (memStore == NULL) {
00062 wsprintf(ErrorMessage, "Attempt to free null memory store");
00063 Box("Error", ErrorMessage, MB_OK | MB_ICONEXCLAMATION);
00064 return;
00065 }
00066
00067
00068 if (memStore->Prev != NULL) {
00069 (memStore->Prev)->Next = memStore->Next;
00070 } else {
00071 MemStoreHead = memStore->Next;
00072 }
00073 if (memStore->Next != NULL) {
00074 (memStore->Next)->Prev = memStore->Prev;
00075 }
00076
00077
00078 ReleaseFree(memStore);
00079
00080 }
00081
00082
00084
00085
00086
00088
00089 MEMSTORE *NextMemStore(MEMSTORE *memStore)
00090 {
00091 if (memStore == NULL) {
00092 return NULL;
00093 }
00094
00095 return memStore->Next;
00096 }
00097
00098
00100
00101
00102
00104
00105 void *DebugMalloc(size_t size, int line, char *file)
00106 {
00107 void *ptr;
00108
00109
00110 ptr = ReleaseMalloc(size + DEBUG_MEMGUARD_SIZE);
00111 if (ptr == NULL) {
00112
00113 wsprintf(ErrorMessage, "Could not Allocate RAM\nLine: %d\nFile: %s", line, file);
00114 if (!AlreadyWarned) {
00115 Box("Error", ErrorMessage, MB_OK | MB_ICONERROR);
00116 AlreadyWarned = TRUE;
00117 }
00118 WriteLogEntry(ErrorMessage);
00119 return NULL;
00120 }
00121
00122
00123 AddMemStore();
00124
00125
00126 MemStoreHead->Ptr = ptr;
00127 MemStoreHead->Size = size;
00128 MemStoreHead->Line = line;
00129 MemStoreHead->File = file;
00130
00131
00132 #if DEBUG_USE_MEMGUARD
00133 *((char *)MemStoreHead->Ptr + MemStoreHead->Size) = (DEBUG_GUARD_TYPE)DEBUG_MEMGUARD_CONTENTS;
00134 #endif
00135
00136
00137 DBG_AllocatedRAM += size;
00138 DBG_NAllocations++;
00139 if (DBG_AllocatedRAM > MaxAllocatedRAM) MaxAllocatedRAM = DBG_AllocatedRAM;
00140
00141 return ptr;
00142 }
00143
00144
00146
00147
00148
00150
00151 void DebugFree(void *ptr, int line, char *file)
00152 {
00153 bool foundPtr;
00154 MEMSTORE *ptrStore, *nextMem;
00155
00156
00157 if (ptr == NULL) {
00158 return;
00159 }
00160
00161
00162 foundPtr = FALSE;
00163 for (nextMem = MemStoreHead; nextMem != NULL; nextMem = NextMemStore(nextMem)) {
00164 if (nextMem->Ptr == ptr) {
00165 ptrStore = nextMem;
00166 foundPtr = TRUE;
00167 break;
00168 }
00169 }
00170
00171
00172 if (!foundPtr) {
00173 wsprintf(ErrorMessage, "Attempt to free non-allocated RAM\nFreed at\n\tLine: %d\n\tFile %s\n", line, file);
00174 if (!AlreadyWarned) {
00175 Box("Error", ErrorMessage, MB_OK | MB_ICONERROR);
00176 AlreadyWarned = TRUE;
00177 }
00178 WriteLogEntry(ErrorMessage);
00179 return;
00180 }
00181
00182
00183 #if DEBUG_USE_MEMGUARD
00184 if (*(DEBUG_MEMGUARD_TYPE *)((char *)ptrStore->Ptr + ptrStore->Size) != DEBUG_MEMGUARD_CONTENTS) {
00185 wsprintf(ErrorMessage, "Guard byte overwritten\nAllocated at\n\tLine: %d\n\tFile %s\nFreed at\n\tLine: %d\n\tFile %s\n", ptrStore->Line, ptrStore->File, line, file);
00186 if (!AlreadyWarned) {
00187 Box("Warning", ErrorMessage, MB_OK | MB_ICONEXCLAMATION);
00188 AlreadyWarned = TRUE;
00189 }
00190 WriteLogEntry(ErrorMessage);
00191 }
00192 #endif
00193
00194
00195 ReleaseFree(ptr);
00196
00197
00198 DBG_AllocatedRAM -= ptrStore->Size;
00199 DBG_NAllocations --;
00200 if (DBG_AllocatedRAM < 0 || DBG_NAllocations < 0) {
00201 wsprintf(ErrorMessage, "Too much memory is being deallocated\n\tLine: %d\n\tFile %s\n(Should never get this message!!)", line, file);
00202 if (!AlreadyWarned) {
00203 Box("Error", ErrorMessage, MB_OK | MB_ICONERROR);
00204 AlreadyWarned = TRUE;
00205 }
00206 WriteLogEntry(ErrorMessage);
00207 return;
00208 }
00209
00210
00211
00212 DeleteMemStore(ptrStore);
00213
00214 }
00215
00216
00218
00219
00220
00221
00223 #if USE_DEBUG_ROUTINES
00224 extern REAL DEBUG_MaxImpulseMag;
00225 extern REAL DEBUG_MaxAngImpulseMag;
00226 #endif
00227
00228 void CheckMemoryAllocation()
00229 {
00230 int iMem;
00231 MEMSTORE *memStore;
00232 FILE *fp;
00233
00234 if (DBG_AllocatedRAM != 0 || DBG_NAllocations != 0) {
00235 wsprintf(ErrorMessage, "Still have RAM allocated\nPrinting log to %s", DBG_LogFile);
00236 Box("Error", ErrorMessage, MB_OK | MB_ICONERROR);
00237 }
00238 if (AlreadyWarned) {
00239 wsprintf(ErrorMessage, "Check Log file \"%s\"", DBG_LogFile);
00240 Box("Error", ErrorMessage, MB_OK | MB_ICONEXCLAMATION);
00241 }
00242 if (TellChris) {
00243 wsprintf(ErrorMessage, "Mail log file \"%s\" to Chris please!", DBG_LogFile);
00244 Box("Mysterious Warning", ErrorMessage, MB_OK | MB_ICONEXCLAMATION);
00245 }
00246
00247 fp = fopen(DBG_LogFile, "a");
00248 if (fp == NULL) {
00249 wsprintf(ErrorMessage, "Could not open log file \"%s\" for writing", DBG_LogFile);
00250 Box("Error", ErrorMessage, MB_OK | MB_ICONERROR);
00251 return;
00252 }
00253
00254
00255 #if USE_DEBUG_ROUTINES
00256 fprintf(fp, "\nMax Impulse Magnitude: %f\n", DEBUG_MaxImpulseMag);
00257 fprintf(fp, "\nMax Ang Imp Magnitude: %f\n\n", DEBUG_MaxAngImpulseMag);
00258 #endif
00259 fprintf(fp, "Max RAM allocated: %ld bytes\n", MaxAllocatedRAM);
00260 fprintf(fp, "RAM still allocated: %ld bytes\n", DBG_AllocatedRAM);
00261 fprintf(fp, "Blocks still allocated: %ld\n\n", DBG_NAllocations);
00262
00263 iMem = 0;
00264 for (memStore = MemStoreHead; memStore != NULL; memStore = NextMemStore(memStore)) {
00265
00266 fprintf(fp, "Block %5d\n", iMem++);
00267 fprintf(fp, "\tSize: %ld bytes\n\tFile: %s\n\tLine: %d\n",
00268 memStore->Size, memStore->File, memStore->Line);
00269 }
00270 fclose(fp);
00271 }
00272
00273 void WriteLogEntry(char *s)
00274 {
00275 FILE *fp;
00276
00277 fp = fopen(DBG_LogFile, "a");
00278 if (fp == NULL) {
00279 return;
00280 }
00281 fprintf(fp, "%s", s);
00282 fclose(fp);
00283 }
00284
00285 void InitLogFile()
00286 {
00287 FILE *fp;
00288
00289 fp = fopen(DBG_LogFile, "w");
00290 if (fp == NULL) {
00291 return;
00292 }
00293
00294 fprintf(fp, "ReVolt Error Log File\n");
00295 fprintf(fp, "Compilation date %s, %s\n\n", __TIME__, __DATE__);
00296
00297 fclose(fp);
00298 }
00299
00301
00302
00303
00304
00306
00307 void DebugAssert(bool result, int line, char *file)
00308 {
00309 if (result) return;
00310
00311 wsprintf(ErrorMessage, "Assertion Failed\nLine: %d\nFile: %s\n", line, file);
00312 if (!AlreadyAsserted) {
00313 Box("Error", ErrorMessage, MB_OK | MB_ICONERROR);
00314 AlreadyAsserted = TRUE;
00315 }
00316 WriteLogEntry(ErrorMessage);
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326 void Error(char *mod, char *func, char *mess, long errno)
00327 {
00328 char buf[256];
00329
00330 wsprintf(buf, "ERROR (%d) in %s - %s", errno, mod, func);
00331 Box(buf, mess, MB_OK | MB_ICONERROR);
00332 WriteLogEntry(ErrorMessage);
00333 QuitGame = TRUE;
00334 }