Textbox "finished". Widget Del methods made private. stb_leakcheck replaced with MemWatch.
This commit is contained in:
parent
b17d78818f
commit
da52b2f675
38 changed files with 7601 additions and 3450 deletions
8
LICENSE
8
LICENSE
|
@ -22,11 +22,11 @@ Licenses Used By:
|
||||||
Client
|
Client
|
||||||
======
|
======
|
||||||
|
|
||||||
stb_ds.h
|
MemWatch
|
||||||
https://github.com/nothings/stb
|
http://www.linkdata.se/sourcecode/memwatch/
|
||||||
Public Domain
|
GPL2
|
||||||
|
|
||||||
stb_leakcheck.h
|
stb_ds.h
|
||||||
https://github.com/nothings/stb
|
https://github.com/nothings/stb
|
||||||
Public Domain
|
Public Domain
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,10 @@ INCLUDEPATH += \
|
||||||
|
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
$$LINUX_HEADERS \
|
$$LINUX_HEADERS \
|
||||||
|
src/thirdparty/stb_ds.h \
|
||||||
|
src/thirdparty/stb_image.h \
|
||||||
|
src/thirdparty/memwatch/memwatch.h \
|
||||||
|
src/gui/memory.h \
|
||||||
src/gui/button.h \
|
src/gui/button.h \
|
||||||
src/gui/checkbox.h \
|
src/gui/checkbox.h \
|
||||||
src/gui/frame.h \
|
src/gui/frame.h \
|
||||||
|
@ -55,9 +59,6 @@ HEADERS = \
|
||||||
src/gui/task.h \
|
src/gui/task.h \
|
||||||
src/gui/textbox.h \
|
src/gui/textbox.h \
|
||||||
src/gui/timer.h \
|
src/gui/timer.h \
|
||||||
src/thirdparty/stb_ds.h \
|
|
||||||
src/thirdparty/stb_leakcheck.h \
|
|
||||||
src/thirdparty/stb_image.h \
|
|
||||||
src/gui/array.h \
|
src/gui/array.h \
|
||||||
src/gui/font.h \
|
src/gui/font.h \
|
||||||
src/gui/desktop.h \
|
src/gui/desktop.h \
|
||||||
|
@ -65,7 +66,6 @@ HEADERS = \
|
||||||
src/gui/widget.h \
|
src/gui/widget.h \
|
||||||
src/gui/window.h \
|
src/gui/window.h \
|
||||||
src/gui/log.h \
|
src/gui/log.h \
|
||||||
src/gui/memory.h \
|
|
||||||
src/gui/mouse.h \
|
src/gui/mouse.h \
|
||||||
src/gui/vesa.h \
|
src/gui/vesa.h \
|
||||||
src/gui/image.h \
|
src/gui/image.h \
|
||||||
|
@ -73,11 +73,12 @@ HEADERS = \
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
$$LINUX_SOURCES \
|
$$LINUX_SOURCES \
|
||||||
|
src/thirdparty/memwatch/memwatch.c \
|
||||||
|
src/gui/memory.c \
|
||||||
src/gui/array.c \
|
src/gui/array.c \
|
||||||
src/gui/font.c \
|
src/gui/font.c \
|
||||||
src/gui/image.c \
|
src/gui/image.c \
|
||||||
src/gui/log.c \
|
src/gui/log.c \
|
||||||
src/gui/memory.c \
|
|
||||||
src/gui/timer.c \
|
src/gui/timer.c \
|
||||||
src/gui/task.c \
|
src/gui/task.c \
|
||||||
src/gui/gui.c \
|
src/gui/gui.c \
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#define ARRAY_H
|
#define ARRAY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
#include "stb_ds.h"
|
#include "stb_ds.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,12 @@
|
||||||
#include "button.h"
|
#include "button.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void buttonDel(WidgetT **widget);
|
||||||
static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
||||||
static void buttonPaint(WidgetT *widget, RectT pos);
|
static void buttonPaint(WidgetT *widget, RectT pos);
|
||||||
|
|
||||||
|
|
||||||
void buttonDel(WidgetT **widget) {
|
static void buttonDel(WidgetT **widget) {
|
||||||
ButtonT *b = (ButtonT *)*widget;
|
ButtonT *b = (ButtonT *)*widget;
|
||||||
|
|
||||||
if (b->title) free(b->title);
|
if (b->title) free(b->title);
|
||||||
|
|
|
@ -33,7 +33,6 @@ typedef struct ButtonS {
|
||||||
} ButtonT;
|
} ButtonT;
|
||||||
|
|
||||||
|
|
||||||
void buttonDel(WidgetT **widget);
|
|
||||||
WidgetT *buttonInit(WidgetT *button, char *title, widgetCallback callback);
|
WidgetT *buttonInit(WidgetT *button, char *title, widgetCallback callback);
|
||||||
ButtonT *buttonNew(uint16_t x, uint16_t y, char *title, widgetCallback callback);
|
ButtonT *buttonNew(uint16_t x, uint16_t y, char *title, widgetCallback callback);
|
||||||
void buttonSetClickHandler(ButtonT *button, widgetCallback callback);
|
void buttonSetClickHandler(ButtonT *button, widgetCallback callback);
|
||||||
|
|
|
@ -21,11 +21,12 @@
|
||||||
#include "checkbox.h"
|
#include "checkbox.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void checkboxDel(WidgetT **widget);
|
||||||
static void checkboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
static void checkboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
||||||
static void checkboxPaint(WidgetT *widget, RectT pos);
|
static void checkboxPaint(WidgetT *widget, RectT pos);
|
||||||
|
|
||||||
|
|
||||||
void checkboxDel(WidgetT **widget) {
|
static void checkboxDel(WidgetT **widget) {
|
||||||
CheckboxT *c = (CheckboxT *)*widget;
|
CheckboxT *c = (CheckboxT *)*widget;
|
||||||
|
|
||||||
if (c->title) free(c->title);
|
if (c->title) free(c->title);
|
||||||
|
|
|
@ -33,7 +33,6 @@ typedef struct CheckboxS {
|
||||||
} CheckboxT;
|
} CheckboxT;
|
||||||
|
|
||||||
|
|
||||||
void checkboxDel(WidgetT **widget);
|
|
||||||
uint8_t checkboxGetValue(CheckboxT *checkbox);
|
uint8_t checkboxGetValue(CheckboxT *checkbox);
|
||||||
WidgetT *checkboxInit(WidgetT *widget, char *title);
|
WidgetT *checkboxInit(WidgetT *widget, char *title);
|
||||||
CheckboxT *checkboxNew(uint16_t x, uint16_t y, char *title);
|
CheckboxT *checkboxNew(uint16_t x, uint16_t y, char *title);
|
||||||
|
|
|
@ -22,10 +22,11 @@
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void desktopDel(WidgetT **widget);
|
||||||
static void desktopPaint(WidgetT *desktop, RectT pos);
|
static void desktopPaint(WidgetT *desktop, RectT pos);
|
||||||
|
|
||||||
|
|
||||||
void desktopDel(WidgetT **widget) {
|
static void desktopDel(WidgetT **widget) {
|
||||||
DesktopT *d = (DesktopT *)*widget;
|
DesktopT *d = (DesktopT *)*widget;
|
||||||
|
|
||||||
vbeSurfaceDestroy(&d->base.surface);
|
vbeSurfaceDestroy(&d->base.surface);
|
||||||
|
|
|
@ -31,7 +31,6 @@ typedef struct DesktopS {
|
||||||
} DesktopT;
|
} DesktopT;
|
||||||
|
|
||||||
|
|
||||||
void desktopDel(WidgetT **widget);
|
|
||||||
WidgetT *desktopInit(WidgetT *desktop);
|
WidgetT *desktopInit(WidgetT *desktop);
|
||||||
DesktopT *desktopNew(void);
|
DesktopT *desktopNew(void);
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,11 @@
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void frameDel(WidgetT **widget);
|
||||||
static void framePaint(WidgetT *widget, RectT pos);
|
static void framePaint(WidgetT *widget, RectT pos);
|
||||||
|
|
||||||
|
|
||||||
void frameDel(WidgetT **widget) {
|
static void frameDel(WidgetT **widget) {
|
||||||
FrameT *f = (FrameT *)*widget;
|
FrameT *f = (FrameT *)*widget;
|
||||||
|
|
||||||
if (f->title) free(f->title);
|
if (f->title) free(f->title);
|
||||||
|
|
|
@ -32,7 +32,6 @@ typedef struct FrameS {
|
||||||
} FrameT;
|
} FrameT;
|
||||||
|
|
||||||
|
|
||||||
void frameDel(WidgetT **widget);
|
|
||||||
WidgetT *frameInit(WidgetT *widget, char *title);
|
WidgetT *frameInit(WidgetT *widget, char *title);
|
||||||
FrameT *frameNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title);
|
FrameT *frameNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title);
|
||||||
void frameSetTitle(FrameT *frame, char *title);
|
void frameSetTitle(FrameT *frame, char *title);
|
||||||
|
|
|
@ -151,7 +151,6 @@ void guiDelete(WidgetT **widget) {
|
||||||
guiDelete(&w->children[x]);
|
guiDelete(&w->children[x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
arrfree(w->children);
|
|
||||||
|
|
||||||
// Delete us.
|
// Delete us.
|
||||||
w->delMethod(&w);
|
w->delMethod(&w);
|
||||||
|
|
|
@ -21,11 +21,12 @@
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void labelDel(WidgetT **widget);
|
||||||
static void labelMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
static void labelMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
||||||
static void labelPaint(WidgetT *widget, RectT pos);
|
static void labelPaint(WidgetT *widget, RectT pos);
|
||||||
|
|
||||||
|
|
||||||
void labelDel(WidgetT **widget) {
|
static void labelDel(WidgetT **widget) {
|
||||||
LabelT *l = (LabelT *)*widget;
|
LabelT *l = (LabelT *)*widget;
|
||||||
|
|
||||||
if (l->title) free(l->title);
|
if (l->title) free(l->title);
|
||||||
|
|
|
@ -36,7 +36,6 @@ typedef struct LabelS {
|
||||||
} LabelT;
|
} LabelT;
|
||||||
|
|
||||||
|
|
||||||
void labelDel(WidgetT **widget);
|
|
||||||
WidgetT *labelInit(WidgetT *widget, char *title);
|
WidgetT *labelInit(WidgetT *widget, char *title);
|
||||||
LabelT *labelNew(uint16_t x, uint16_t y, char *title);
|
LabelT *labelNew(uint16_t x, uint16_t y, char *title);
|
||||||
void labelSetActiveColor(LabelT *label, ColorT color);
|
void labelSetActiveColor(LabelT *label, ColorT color);
|
||||||
|
|
|
@ -18,5 +18,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define STB_LEAKCHECK_IMPLEMENTATION
|
#include "memory.h"
|
||||||
#include "stb_leakcheck.h"
|
|
||||||
|
|
||||||
|
#ifdef MEMWATCH_STDIO
|
||||||
|
void memoryOutput(int c) {
|
||||||
|
putchar(c);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void memoryShutdown(void) {
|
||||||
|
// Nada.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void memoryStartup(void) {
|
||||||
|
#ifdef MEMWATCH_STDIO
|
||||||
|
mwSetOutFunc(memoryOutput);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -22,10 +22,15 @@
|
||||||
#define MEMORY_H
|
#define MEMORY_H
|
||||||
|
|
||||||
|
|
||||||
#include "stb_leakcheck.h"
|
#include "os.h"
|
||||||
|
|
||||||
|
#define MEMWATCH
|
||||||
|
#define MEMWATCH_STDIO
|
||||||
|
#include "memwatch/memwatch.h"
|
||||||
|
|
||||||
|
|
||||||
#define memoryLeaksShow stb_leakcheck_dumpmem
|
void memoryShutdown(void);
|
||||||
|
void memoryStartup(void);
|
||||||
|
|
||||||
|
|
||||||
#endif // MEMORY_H
|
#endif // MEMORY_H
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#define OS_H
|
#define OS_H
|
||||||
|
|
||||||
|
|
||||||
|
// Common platform includes.
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -33,10 +34,12 @@
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
|
||||||
|
// Linux DOS replacements.
|
||||||
long biostime(int cmd, long newtime);
|
long biostime(int cmd, long newtime);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
// DOS includes.
|
||||||
#include <dos.h>
|
#include <dos.h>
|
||||||
#include <dpmi.h>
|
#include <dpmi.h>
|
||||||
#include <go32.h>
|
#include <go32.h>
|
||||||
|
@ -47,13 +50,14 @@ long biostime(int cmd, long newtime);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Has to be after system headers in this file.
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
// Now our headers.
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
|
||||||
// Has to be after system headers in this file.
|
// Some helper defines.
|
||||||
//#include "memory.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))
|
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))
|
||||||
#define HIGH_BYTE(b) ((uint8_t)(((b) & 0xFF00) >> 8))
|
#define HIGH_BYTE(b) ((uint8_t)(((b) & 0xFF00) >> 8))
|
||||||
#define LOW_BYTE(b) ((uint8_t)((b) & 0x00FF))
|
#define LOW_BYTE(b) ((uint8_t)((b) & 0x00FF))
|
||||||
|
|
|
@ -21,11 +21,12 @@
|
||||||
#include "picture.h"
|
#include "picture.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void pictureDel(WidgetT **widget);
|
||||||
static void pictureMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
static void pictureMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
||||||
static void picturePaint(WidgetT *widget, RectT pos);
|
static void picturePaint(WidgetT *widget, RectT pos);
|
||||||
|
|
||||||
|
|
||||||
void pictureDel(WidgetT **widget) {
|
static void pictureDel(WidgetT **widget) {
|
||||||
PictureT *p = (PictureT *)*widget;
|
PictureT *p = (PictureT *)*widget;
|
||||||
|
|
||||||
if (p->image) imageUnload(&p->image);
|
if (p->image) imageUnload(&p->image);
|
||||||
|
|
|
@ -35,7 +35,6 @@ typedef struct PictureS {
|
||||||
} PictureT;
|
} PictureT;
|
||||||
|
|
||||||
|
|
||||||
void pictureDel(WidgetT **widget);
|
|
||||||
WidgetT *pictureInit(WidgetT *widget, char *filename);
|
WidgetT *pictureInit(WidgetT *widget, char *filename);
|
||||||
PictureT *pictureNew(uint16_t x, uint16_t y, char *filename);
|
PictureT *pictureNew(uint16_t x, uint16_t y, char *filename);
|
||||||
void pictureSetClickHandler(PictureT *picture, widgetCallback callback);
|
void pictureSetClickHandler(PictureT *picture, widgetCallback callback);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
static void radioClearSelectedInGroup(WidgetT *widget, uint32_t group);
|
static void radioClearSelectedInGroup(WidgetT *widget, uint32_t group);
|
||||||
|
static void radioDel(WidgetT **widget);
|
||||||
static RadioT *radioFindSelectedInGroup(WidgetT *widget, uint32_t group);
|
static RadioT *radioFindSelectedInGroup(WidgetT *widget, uint32_t group);
|
||||||
static void radioMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
static void radioMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
||||||
static void radioPaint(WidgetT *widget, RectT pos);
|
static void radioPaint(WidgetT *widget, RectT pos);
|
||||||
|
@ -51,7 +52,7 @@ static void radioClearSelectedInGroup(WidgetT *widget, uint32_t group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void radioDel(WidgetT **widget) {
|
static void radioDel(WidgetT **widget) {
|
||||||
RadioT *r = (RadioT *)*widget;
|
RadioT *r = (RadioT *)*widget;
|
||||||
|
|
||||||
if (r->title) free(r->title);
|
if (r->title) free(r->title);
|
||||||
|
|
|
@ -34,7 +34,6 @@ typedef struct RadioS {
|
||||||
} RadioT;
|
} RadioT;
|
||||||
|
|
||||||
|
|
||||||
void radioDel(WidgetT **widget);
|
|
||||||
RadioT *radioGetSelected(RadioT *radio);
|
RadioT *radioGetSelected(RadioT *radio);
|
||||||
WidgetT *radioInit(WidgetT *widget, char *title, uint16_t group);
|
WidgetT *radioInit(WidgetT *widget, char *title, uint16_t group);
|
||||||
RadioT *radioNew(uint16_t x, uint16_t y, char *title, uint16_t group);
|
RadioT *radioNew(uint16_t x, uint16_t y, char *title, uint16_t group);
|
||||||
|
|
|
@ -22,13 +22,14 @@
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void textboxDel(WidgetT **widget);
|
||||||
static void textboxFocusEvent(WidgetT *widget, uint8_t focused);
|
static void textboxFocusEvent(WidgetT *widget, uint8_t focused);
|
||||||
static void textboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
static void textboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
||||||
static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
||||||
static void textboxPaint(WidgetT *widget, RectT pos);
|
static void textboxPaint(WidgetT *widget, RectT pos);
|
||||||
|
|
||||||
|
|
||||||
void textboxDel(WidgetT **widget) {
|
static void textboxDel(WidgetT **widget) {
|
||||||
TextboxT *t = (TextboxT *)*widget;
|
TextboxT *t = (TextboxT *)*widget;
|
||||||
|
|
||||||
if (t->title) free(t->title);
|
if (t->title) free(t->title);
|
||||||
|
@ -158,7 +159,7 @@ static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extende
|
||||||
default: // Other keys
|
default: // Other keys
|
||||||
if (ascii >= 32 && ascii <= 126) {
|
if (ascii >= 32 && ascii <= 126) {
|
||||||
// Insert character, if room.
|
// Insert character, if room.
|
||||||
if (strlen(t->value) < t->maxLength - 1) {
|
if (strlen(t->value) < (size_t)t->maxLength - 1) {
|
||||||
// Move existing characters over, if needed.
|
// Move existing characters over, if needed.
|
||||||
if (t->caret + t->offset < strlen(t->value)) {
|
if (t->caret + t->offset < strlen(t->value)) {
|
||||||
for (x=strlen(t->value) + 1; x>t->caret + t->offset; x--) {
|
for (x=strlen(t->value) + 1; x>t->caret + t->offset; x--) {
|
||||||
|
@ -189,14 +190,30 @@ static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extende
|
||||||
|
|
||||||
static void textboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event) {
|
static void textboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event) {
|
||||||
TextboxT *t = (TextboxT *)widget;
|
TextboxT *t = (TextboxT *)widget;
|
||||||
|
RectT textArea;
|
||||||
|
|
||||||
(void)x;
|
(void)x;
|
||||||
(void)y;
|
(void)y;
|
||||||
(void)mouse;
|
(void)mouse;
|
||||||
|
|
||||||
//***TODO*** Allow dragging/positioning text cursor with mouse.
|
// Allow dragging/positioning text cursor with mouse.
|
||||||
if (event == MOUSE_EVENT_LEFT_HOLD) {
|
if (event == MOUSE_EVENT_LEFT_HOLD) {
|
||||||
|
// Where's the text display?
|
||||||
|
textArea.x = (strlen(t->title) * fontWidthGet(_guiFont)) + _guiMetric[METRIC_TEXTBOX_PADDING] + 2 + _guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING];
|
||||||
|
textArea.y = 2 + _guiMetric[METRIC_TEXTBOX_VERTICAL_PADDING];
|
||||||
|
textArea.w = textArea.x + t->visible * fontWidthGet(_guiFont);
|
||||||
|
textArea.h = textArea.y + fontHeightGet(_guiFont);
|
||||||
|
// Is the pointer over it?
|
||||||
|
if (x >= textArea.x && x < textArea.w && y >= textArea.y && y < textArea.h) {
|
||||||
|
// Move caret.
|
||||||
|
t->caret = (x - textArea.x) / fontWidthGet(_guiFont);
|
||||||
|
// Did we go too far?
|
||||||
|
if (t->caret + t->offset > strlen(t->value)) {
|
||||||
|
t->caret = strlen(t->value) - t->offset;
|
||||||
|
}
|
||||||
|
// Ensure we redraw.
|
||||||
|
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,14 +267,13 @@ static void textboxPaint(WidgetT *widget, RectT pos) {
|
||||||
|
|
||||||
// Draw value. ***TODO*** This needs much more! Do it without strdup?
|
// Draw value. ***TODO*** This needs much more! Do it without strdup?
|
||||||
draw = strdup(&t->value[t->offset]);
|
draw = strdup(&t->value[t->offset]);
|
||||||
if (strlen(t->value) > t->visible) draw[t->visible] = 0;
|
if (strlen(draw) > t->visible) draw[t->visible] = 0;
|
||||||
fontRender(_guiFont, draw, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], textX, textY);
|
fontRender(_guiFont, draw, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], textX, textY);
|
||||||
free(draw);
|
free(draw);
|
||||||
|
|
||||||
// Draw cursor.
|
// Draw cursor.
|
||||||
if (guiFocusGet() == widget && timerQuarterSecondOn) {
|
if (guiFocusGet() == widget && timerQuarterSecondOn) {
|
||||||
caretPos = textX + fontWidthGet(_guiFont) * t->caret;
|
caretPos = textX + fontWidthGet(_guiFont) * t->caret;
|
||||||
//logWrite("textX %d textY %d caretPos %d\n", textX, textY, caretPos);
|
|
||||||
fontRender(_guiFont, cursor, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], caretPos, textY);
|
fontRender(_guiFont, cursor, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], caretPos, textY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,7 +287,7 @@ void textboxSetValue(TextboxT *textbox, char *value) {
|
||||||
strncpy(textbox->value, value, textbox->maxLength - 1);
|
strncpy(textbox->value, value, textbox->maxLength - 1);
|
||||||
|
|
||||||
// Is this longer than the area we have to display it in?
|
// Is this longer than the area we have to display it in?
|
||||||
if (strlen(textbox->value) > textbox->visible - 1) {
|
if (strlen(textbox->value) > (size_t)(textbox->visible - 1)) {
|
||||||
textbox->offset = strlen(textbox->value) - (textbox->visible - 1);
|
textbox->offset = strlen(textbox->value) - (textbox->visible - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ typedef struct TextboxS {
|
||||||
} TextboxT;
|
} TextboxT;
|
||||||
|
|
||||||
|
|
||||||
void textboxDel(WidgetT **widget);
|
|
||||||
char *textboxGetValue(TextboxT *textbox);
|
char *textboxGetValue(TextboxT *textbox);
|
||||||
WidgetT *textboxInit(WidgetT *widget, char *title);
|
WidgetT *textboxInit(WidgetT *widget, char *title);
|
||||||
TextboxT *textboxNew(uint16_t x, uint16_t y, uint16_t w, char *title);
|
TextboxT *textboxNew(uint16_t x, uint16_t y, uint16_t w, char *title);
|
||||||
|
|
|
@ -22,6 +22,17 @@
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void widgetDel(WidgetT **widget);
|
||||||
|
|
||||||
|
|
||||||
|
static void widgetDel(WidgetT **widget) {
|
||||||
|
WidgetT *w = (WidgetT *)*widget;
|
||||||
|
|
||||||
|
free(w);
|
||||||
|
w = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t widgetHeightGet(WidgetT *widget) {
|
uint16_t widgetHeightGet(WidgetT *widget) {
|
||||||
return widget->pos.h;
|
return widget->pos.h;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +57,7 @@ WidgetT *widgetInit(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint
|
||||||
widget->children = NULL;
|
widget->children = NULL;
|
||||||
widget->parent = NULL;
|
widget->parent = NULL;
|
||||||
widget->window = NULL;
|
widget->window = NULL;
|
||||||
widget->delMethod = NULL;
|
widget->delMethod = widgetDel;
|
||||||
widget->focusMethod = NULL;
|
widget->focusMethod = NULL;
|
||||||
widget->keyboardEventMethod = NULL;
|
widget->keyboardEventMethod = NULL;
|
||||||
widget->paintMethod = NULL;
|
widget->paintMethod = NULL;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
static void windowDeactivateAll(WidgetT *widget);
|
static void windowDeactivateAll(WidgetT *widget);
|
||||||
|
static void windowDel(WidgetT **widget);
|
||||||
static void windowMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
static void windowMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
||||||
static void windowPaint(WidgetT *widget, RectT pos);
|
static void windowPaint(WidgetT *widget, RectT pos);
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ static void windowDeactivateAll(WidgetT *widget) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void windowDel(WidgetT **widget) {
|
static void windowDel(WidgetT **widget) {
|
||||||
WindowT *w = (WindowT *)*widget;
|
WindowT *w = (WindowT *)*widget;
|
||||||
|
|
||||||
vbeSurfaceDestroy(&w->base.surface);
|
vbeSurfaceDestroy(&w->base.surface);
|
||||||
|
|
|
@ -39,7 +39,6 @@ typedef struct WindowS {
|
||||||
} WindowT;
|
} WindowT;
|
||||||
|
|
||||||
|
|
||||||
void windowDel(WidgetT **widget);
|
|
||||||
WidgetT *windowInit(WidgetT *window, char *title);
|
WidgetT *windowInit(WidgetT *window, char *title);
|
||||||
WindowT *windowNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title);
|
WindowT *windowNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title);
|
||||||
void windowSetActive(WindowT *window);
|
void windowSetActive(WindowT *window);
|
||||||
|
|
|
@ -199,6 +199,8 @@ int main(int argc, char *argv[]) {
|
||||||
char *c = NULL;
|
char *c = NULL;
|
||||||
int16_t x = strlen(argv[0]);
|
int16_t x = strlen(argv[0]);
|
||||||
|
|
||||||
|
memoryStartup();
|
||||||
|
|
||||||
// 0 1 2 3 4 5 6 7 8
|
// 0 1 2 3 4 5 6 7 8
|
||||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||||
printf("Kangaroo Punch MultiPlayer DOS Game Client Mark II\n");
|
printf("Kangaroo Punch MultiPlayer DOS Game Client Mark II\n");
|
||||||
|
@ -222,6 +224,7 @@ int main(int argc, char *argv[]) {
|
||||||
// Command line needs to have the desired resolution and color depth on it.
|
// Command line needs to have the desired resolution and color depth on it.
|
||||||
if (argc != 4) {
|
if (argc != 4) {
|
||||||
vbeShowInfo();
|
vbeShowInfo();
|
||||||
|
memoryShutdown();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
xResolution = atoi(argv[1]);
|
xResolution = atoi(argv[1]);
|
||||||
|
@ -230,6 +233,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
// Do we have the video mode they asked for?
|
// Do we have the video mode they asked for?
|
||||||
if (vbeStartup(xResolution, yResolution, colorDepth)) {
|
if (vbeStartup(xResolution, yResolution, colorDepth)) {
|
||||||
|
memoryShutdown();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,11 +252,9 @@ int main(int argc, char *argv[]) {
|
||||||
mouseShutdown();
|
mouseShutdown();
|
||||||
vbeShutdown();
|
vbeShutdown();
|
||||||
|
|
||||||
#ifdef memoryLeakShow
|
|
||||||
memoryLeaksShow();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
logClose();
|
logClose();
|
||||||
|
|
||||||
|
memoryShutdown();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
133
client/src/thirdparty/memwatch/FAQ
vendored
Normal file
133
client/src/thirdparty/memwatch/FAQ
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
Frequently Asked Questions for memwatch
|
||||||
|
|
||||||
|
Q. I'm not getting any log file! What's wrong??
|
||||||
|
|
||||||
|
A. Did you define MEMWATCH when compiling all files?
|
||||||
|
Did you include memwatch.h in all the files?
|
||||||
|
If you did, then...:
|
||||||
|
|
||||||
|
Memwatch creates the file when it initializes. If you're not
|
||||||
|
getting the log file, it's because a) memwatch is not
|
||||||
|
initializing or b) it's initializing, but can't create the
|
||||||
|
file.
|
||||||
|
|
||||||
|
Memwatch has two functions, mwInit() and mwTerm(), that
|
||||||
|
initialize and terminate memwatch, respectively. They are
|
||||||
|
nestable. You USUALLY don't need to call mwInit() and
|
||||||
|
mwTerm(), since memwatch will auto-initialize on the first
|
||||||
|
call to a memory function, and then add mwTerm() to the
|
||||||
|
atexit() list.
|
||||||
|
|
||||||
|
You can call mwInit() and mwTerm() manually, if it's not
|
||||||
|
initializing properly or if your system doesn't support
|
||||||
|
atexit(). Call mwInit() as soon as you can, and mwTerm() at
|
||||||
|
the logical no-error ending of your program. Call mwAbort()
|
||||||
|
if the program is stopping due to an error; this will
|
||||||
|
terminate memwatch even if more than one call to mwTerm() is
|
||||||
|
outstanding.
|
||||||
|
|
||||||
|
If you are using C++, remember that global and static C++
|
||||||
|
objects constructors execute before main() when considering
|
||||||
|
where to put mwInit(). Also, their destructors execute after
|
||||||
|
main(). You may want to create a global object very early
|
||||||
|
with mwInit() in the constructor and mwTerm() in the
|
||||||
|
destructor. Too bad C++ does not guarantee initialization
|
||||||
|
order for global objects.
|
||||||
|
|
||||||
|
If this didn't help, try adding a call to mwDoFlush(1) after
|
||||||
|
mwInit(). If THAT didn't help, then memwatch is unable to
|
||||||
|
create the log file. Check write permissions.
|
||||||
|
|
||||||
|
If you can't use a log file, you can still use memwatch by
|
||||||
|
redirecting the output to a function of your choice. See the
|
||||||
|
next question.
|
||||||
|
|
||||||
|
Q. I'd like memwatch's output to pipe to my fave debugger! How?
|
||||||
|
|
||||||
|
A. Call mwSetOutFunc() with the address of a "void func(int c)"
|
||||||
|
function. You should also consider doing something about
|
||||||
|
the ARI handler, see memwatch.h for more details about that.
|
||||||
|
|
||||||
|
Q. Why isn't there any C++ support?
|
||||||
|
|
||||||
|
A. Because C++ is for sissies! =) Just kidding.
|
||||||
|
C++ comes with overridable allocation/deallocation
|
||||||
|
built-in. You can define your own new/delete operators
|
||||||
|
for any class, and thus circumvent memwatch, or confuse
|
||||||
|
it to no end. Also, the keywords "new" and "delete" may
|
||||||
|
appear in declarations in C++, making the preprocessor
|
||||||
|
replacement approach shaky. You can do it, but it's not
|
||||||
|
very stable.
|
||||||
|
|
||||||
|
If someone were to write a rock solid new/delete checker
|
||||||
|
for C++, there is no conflict with memwatch; use them both.
|
||||||
|
|
||||||
|
Q. I'm getting "WILD free" errors, but the code is bug-free!
|
||||||
|
|
||||||
|
A. If memwatch's free() recieves a pointer that wasn't allocated
|
||||||
|
by memwatch, a "WILD free" message appears. If the source of
|
||||||
|
the memory buffer is outside of memwatch (a non-standard
|
||||||
|
library function, for instance), you can use mwFree_() to
|
||||||
|
release it. mwFree_() calls free() on the pointer given if
|
||||||
|
memwatch can't recognize it, instead of blocking it.
|
||||||
|
|
||||||
|
Another source of "WILD free" messages is that if memwatch
|
||||||
|
is terminated before all memory allocated is freed, memwatch
|
||||||
|
will have forgotten about it, and thus generate the errors.
|
||||||
|
This is commonly caused by having memwatch auto-initialize,
|
||||||
|
and then using atexit() to clean up. When auto-initializing,
|
||||||
|
memwatch registers mwTerm() with atexit(), but if mwTerm()
|
||||||
|
runs before all memory is freed, then you will get "unfreed"
|
||||||
|
and "WILD free" messages when your own atexit()-registered
|
||||||
|
cleanup code runs, and frees the memory.
|
||||||
|
|
||||||
|
Q. I'm getting "unfreed" errors, but the code is bug-free!
|
||||||
|
|
||||||
|
A. You can get erroneous "unfreed" messages if memwatch
|
||||||
|
terminates before all memory has been freed. Try using
|
||||||
|
mwInit() and mwTerm() instead of auto-initialization.
|
||||||
|
|
||||||
|
If you _are_ using mwInit() and mwTerm(), it may be that
|
||||||
|
some code in your program executes before mwInit() or
|
||||||
|
after mwTerm(). Make sure that mwInit() is the first thing
|
||||||
|
executed, and mwTerm() the last.
|
||||||
|
|
||||||
|
Q. When compiling memwatch I get these 'might get clobbered'
|
||||||
|
errors, and something about a longjmp() inside memwatch.
|
||||||
|
|
||||||
|
A. When using gcc or egcs with the optimization to inline
|
||||||
|
functions, this warning occurs. This is because gcc and
|
||||||
|
egcs inlines memwatch's functions with setjmp/longjmp,
|
||||||
|
causing the calling functions to become unstable.
|
||||||
|
|
||||||
|
The gcc/egcs maintainers have been informed of this
|
||||||
|
problem, but until they modify the inline optimization
|
||||||
|
so that it leaves setjmp functions alone, make sure to
|
||||||
|
compile memwatch without inline function optimizations.
|
||||||
|
|
||||||
|
gcc 2.95.2 can be patched for this, and I have been told
|
||||||
|
it will be fixed in an upcoming version.
|
||||||
|
|
||||||
|
Q. My program crashes with SIGSEGV or alignment errors, but
|
||||||
|
only when I compile with memwatch enabled!
|
||||||
|
|
||||||
|
A. You are using a 64-bit (or higher) platform, and memwatch
|
||||||
|
was unable to detect and adjust for this. You'll have to
|
||||||
|
either compile with a suitable define for mwROUNDALLOC,
|
||||||
|
I suggest (number of bits / 8), or define mwROUNDALLOC
|
||||||
|
directly in memwatch.c.
|
||||||
|
|
||||||
|
Also, please check your limits.h file for the relevant
|
||||||
|
#defines, and tell me what they are.
|
||||||
|
|
||||||
|
Q. When I include string.h after memwatch.h, I get errors
|
||||||
|
related to strdup(), what gives?
|
||||||
|
|
||||||
|
A. Most, but probably not all, platforms are nice about
|
||||||
|
including files multiple times, so I could probably
|
||||||
|
avoid these errors by including string.h from memwatch.h.
|
||||||
|
But since I want to be on the safe side, I don't.
|
||||||
|
|
||||||
|
To fix this, simply include string.h before memwatch.h,
|
||||||
|
or modify memwatch.h to include string.h.
|
||||||
|
|
2
client/src/thirdparty/memwatch/Makefile
vendored
Normal file
2
client/src/thirdparty/memwatch/Makefile
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
test:
|
||||||
|
$(CC) -DMEMWATCH -DMW_STDIO test.c memwatch.c
|
99
client/src/thirdparty/memwatch/README
vendored
Normal file
99
client/src/thirdparty/memwatch/README
vendored
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
README for MEMWATCH 2.69
|
||||||
|
|
||||||
|
This file should be enough to get you started, and should be
|
||||||
|
enough for small projects. For more info, see the files USING
|
||||||
|
and the FAQ. If this is not enough, see memwatch.h, which is
|
||||||
|
well documented.
|
||||||
|
|
||||||
|
Memwatch is licensed under the GPL from version 2.69
|
||||||
|
onwards. Please read the file gpl.txt for more details.
|
||||||
|
|
||||||
|
If you choose to use memwatch to validate your projects, I
|
||||||
|
would like to hear about it. Please drop me a line at
|
||||||
|
johan@linkdata.se about the project itself, the hardware,
|
||||||
|
operating system, compiler and any URL(s) you feel is
|
||||||
|
appropriate.
|
||||||
|
|
||||||
|
***** To run the test program:
|
||||||
|
|
||||||
|
Look at the source code for test.c first. It does some really
|
||||||
|
nasty things, and I want you to be aware of that. If memwatch
|
||||||
|
can't capture SIGSEGV (General Protection Fault for Windoze),
|
||||||
|
your program will dump core (crash for Windoze).
|
||||||
|
|
||||||
|
Once you've done that, you can build the test program.
|
||||||
|
|
||||||
|
Linux and other *nixes with gcc:
|
||||||
|
|
||||||
|
gcc -o test -DMEMWATCH -DMEMWATCH_STDIO test.c memwatch.c
|
||||||
|
|
||||||
|
Windows 95, Windows NT with MS Visual C++:
|
||||||
|
|
||||||
|
cl -DMEMWATCH -DMEMWATCH_STDIO test.c memwatch.c
|
||||||
|
|
||||||
|
Then simply run the test program.
|
||||||
|
|
||||||
|
./test
|
||||||
|
|
||||||
|
|
||||||
|
***** Quick-start instructions:
|
||||||
|
|
||||||
|
1. Make sure that memwatch.h is included in all of the
|
||||||
|
source code files. If you have an include file that
|
||||||
|
all of the source code uses, you might be able to include
|
||||||
|
memwatch.h from there.
|
||||||
|
|
||||||
|
2. Recompile the program with MEMWATCH defined. See your
|
||||||
|
compiler's documentation if you don't know how to do this.
|
||||||
|
The usual switch looks like "-DMEMWATCH". To have MEMWATCH
|
||||||
|
use stderr for some output (like, "Abort, Retry, Ignore?"),
|
||||||
|
please also define MW_STDIO (or MEMWATCH_STDIO, same thing).
|
||||||
|
|
||||||
|
3. Run the program and examine the output in the
|
||||||
|
log file "memwatch.log". If you didn't get a log file,
|
||||||
|
you probably didn't do step 1 and 2 correctly, or your
|
||||||
|
program crashed before memwatch flushed the file buffer.
|
||||||
|
To have memwatch _always_ flush the buffer, add a call
|
||||||
|
to "mwDoFlush(1)" at the top of your main function.
|
||||||
|
|
||||||
|
4. There is no fourth step... but remember that there
|
||||||
|
are limits to what memwatch can do, and that you need
|
||||||
|
to be aware of them:
|
||||||
|
|
||||||
|
***** Limits to memwatch:
|
||||||
|
|
||||||
|
Memwatch cannot catch all wild pointer writes. It can catch
|
||||||
|
those it could make itself due to your program trashing
|
||||||
|
memwatch's internal data structures. It can catch, sort of,
|
||||||
|
wild writes into No Mans Land buffers (see the header file for
|
||||||
|
more info). Anything else and you're going to get core dumped,
|
||||||
|
or data corruption if you're lucky.
|
||||||
|
|
||||||
|
There are other limits of course, but that one is the most
|
||||||
|
serious one, and the one that you're likely to be suffering
|
||||||
|
from.
|
||||||
|
|
||||||
|
***** Can use memwatch with XXXXX?
|
||||||
|
|
||||||
|
Probably the answer is yes. It's been tested with several
|
||||||
|
different platforms and compilers. It may not work on yours
|
||||||
|
though... but there's only one way to find out.
|
||||||
|
|
||||||
|
***** Need more assistance?
|
||||||
|
|
||||||
|
I don't want e-mail on "how to program in C", or "I've got a
|
||||||
|
bug, help me". I _do_ want you to send email to me if you
|
||||||
|
find a bug in memwatch, or if it won't compile cleanly on your
|
||||||
|
system (assuming it's an ANSI-C compiler of course).
|
||||||
|
|
||||||
|
If you need help with using memwatch, read the header file.
|
||||||
|
If, after reading the header file, you still can't resolve the
|
||||||
|
problem, please mail me with the details.
|
||||||
|
|
||||||
|
I can be reached at "johan@linkdata.se".
|
||||||
|
|
||||||
|
The latest version of memwatch should be found at
|
||||||
|
"http://www.linkdata.se/".
|
||||||
|
|
||||||
|
Johan Lindh
|
||||||
|
|
213
client/src/thirdparty/memwatch/USING
vendored
Normal file
213
client/src/thirdparty/memwatch/USING
vendored
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
Using memwatch
|
||||||
|
==============
|
||||||
|
|
||||||
|
What is it?
|
||||||
|
|
||||||
|
Memwatch is primarily a memory leak detector for C. Besides
|
||||||
|
detecting leaks, it can do a bunch of other stuff, but lets
|
||||||
|
stay to the basics. If you _really_ want to know all the
|
||||||
|
gory details, you should check out the header file,
|
||||||
|
memwatch.h, and the source code. It's actually got some
|
||||||
|
comments! (Whoa, what a concept!)
|
||||||
|
|
||||||
|
How do I get the latest version?
|
||||||
|
|
||||||
|
http://www.linkdata.se/sourcecode.html
|
||||||
|
ftp://ftp.linkdata.se/pub/memwatch/
|
||||||
|
|
||||||
|
How does it work?
|
||||||
|
|
||||||
|
Using the C preprocessor, memwatch replaces all your
|
||||||
|
programs calls to ANSI C memory allocation functions with
|
||||||
|
calls to it's own functions, which keeps a record of all
|
||||||
|
allocations.
|
||||||
|
|
||||||
|
Memwatch is very unobtrusive; unless the define MEMWATCH is
|
||||||
|
defined, memwatch removes all traces of itself from the
|
||||||
|
code (using the preprocessor).
|
||||||
|
|
||||||
|
Memwatch normally writes it's data to the file
|
||||||
|
memwatch.log, but this can be overridden; see the section
|
||||||
|
on I/O, later.
|
||||||
|
|
||||||
|
Can I use it for my C++ sources?
|
||||||
|
|
||||||
|
You can, but it's not recommended. C++ allows individual
|
||||||
|
classes to have their own memory management, and the
|
||||||
|
preprocessor approach used by memwatch can cause havoc
|
||||||
|
with such class declarations if improperly used.
|
||||||
|
|
||||||
|
If you have no such classes, or have them but still want
|
||||||
|
to test it, you can give it a try.
|
||||||
|
|
||||||
|
First, re-enable the C++ support code in memwatch.
|
||||||
|
If you can't find it, you probably shouldn't be using
|
||||||
|
it. Then, in your source code, after including ALL
|
||||||
|
header files:
|
||||||
|
|
||||||
|
#define new mwNew
|
||||||
|
#define delete mwDelete
|
||||||
|
|
||||||
|
This will cause calls to new and delete in that source file
|
||||||
|
to be directed to memwatch. Also, be sure to read all the
|
||||||
|
text in memwatch.h regarding C++ support.
|
||||||
|
|
||||||
|
Is this stuff thread-safe?
|
||||||
|
|
||||||
|
I doubt it. As of version 2.66, there is rudimentary support
|
||||||
|
for threads, if you happen to be using Win32 or if you have
|
||||||
|
pthreads. Define WIN32 or MW_PTHREADS to signify this fact.
|
||||||
|
|
||||||
|
This will cause a global mutex to be created, and memwatch
|
||||||
|
will lock it when accessing the global memory chain, but it's
|
||||||
|
still far from certified threadsafe.
|
||||||
|
|
||||||
|
Initialization and cleanup
|
||||||
|
|
||||||
|
In order to do it's work in a timely fashion, memwatch
|
||||||
|
needs to do some startup and cleanup work. mwInit()
|
||||||
|
initializes memwatch and mwTerm() terminates it. Memwatch
|
||||||
|
can auto-initialize, and will do so if you don't call
|
||||||
|
mwInit() yourself. If this is the case, memwatch will use
|
||||||
|
atexit() to register mwTerm() to the atexit-queue.
|
||||||
|
|
||||||
|
The auto-init technique has a caveat; if you are using
|
||||||
|
atexit() yourself to do cleanup work, memwatch may
|
||||||
|
terminate before your program is done. To be on the safe
|
||||||
|
side, use mwInit() and mwTerm().
|
||||||
|
|
||||||
|
mwInit() and mwTerm() is nestable, so you can call mwInit()
|
||||||
|
several times, requiring mwTerm() to be called an equal
|
||||||
|
number of times to terminate memwatch.
|
||||||
|
|
||||||
|
In case of the program aborting in a controlled way, you
|
||||||
|
may want to call mwAbort() instead of mwTerm(). mwAbort()
|
||||||
|
will terminate memwatch even if there are outstanding calls
|
||||||
|
to mwTerm().
|
||||||
|
|
||||||
|
I/O operations
|
||||||
|
|
||||||
|
During normal operations, memwatch creates a file named
|
||||||
|
memwatch.log. Sometimes, memwatch.log can't be created;
|
||||||
|
then memwatch tries to create files name memwatNN.log,
|
||||||
|
where NN is between 01 and 99. If that fails, no log will
|
||||||
|
be produced.
|
||||||
|
|
||||||
|
If you can't use a file log, or don't want to, no worry.
|
||||||
|
Just call mwSetOutFunc() with the address of a "void
|
||||||
|
func(int c)" function, and all output will be directed
|
||||||
|
there, character by character.
|
||||||
|
|
||||||
|
Memwatch also has an Abort/Retry/Ignore handler that is
|
||||||
|
used when an ASSERT or VERIFY fails. The default handler
|
||||||
|
does no I/O, but automatically aborts the program. You can
|
||||||
|
use any handler you want; just send the address of a "int
|
||||||
|
func(const char*)" to mwSetAriFunc(). For more details on
|
||||||
|
that, see memwatch.h.
|
||||||
|
|
||||||
|
TRACE/ASSERT/VERIFY macros
|
||||||
|
|
||||||
|
Memwatch defines (if not already defined) the macros TRACE,
|
||||||
|
ASSERT and VERIFY. If you are already using macros with
|
||||||
|
these names, memwatch 2.61 and later will not override
|
||||||
|
them. Memwatch 2.61 and later will also always define the
|
||||||
|
macros mwTRACE, mwASSERT and mwVERIFY, so you can use these
|
||||||
|
to make sure you're talking to memwatch. Versions prior
|
||||||
|
to 2.61 will *OVERRIDE* existing TRACE, ASSERT and VERIFY.
|
||||||
|
|
||||||
|
To make sure that existing TRACE, ASSERT and VERIFY macros
|
||||||
|
are preserved, you can define MW_NOTRACE, MW_NOASSERT and
|
||||||
|
MW_NOVERIFY. All versions of memwatch will abide by these.
|
||||||
|
|
||||||
|
How slow can you go?
|
||||||
|
|
||||||
|
Memwatch slows things down. Large allocations aren't
|
||||||
|
affected so that you can measure it, but small allocations
|
||||||
|
that would utilize a compilers small-allocator function
|
||||||
|
suddenly cannot, and so gets slowed down alot. As a worst
|
||||||
|
case, expect it to be 3-5 times slower.
|
||||||
|
|
||||||
|
Free'ing gets hit worse, I'm afraid, as memwatch checks
|
||||||
|
a lot of stuff when freeing. Expect it to be 5-7 times
|
||||||
|
slower, no matter what the size of the allocation.
|
||||||
|
|
||||||
|
Stress-testing the application
|
||||||
|
|
||||||
|
You can simulate low-memory conditions using mwLimit().
|
||||||
|
mwLimit() takes the maximum number of bytes to be
|
||||||
|
allocated; when the limit is hit, allocation requests will
|
||||||
|
fail, and a "limit" message will be logged.
|
||||||
|
|
||||||
|
If you hit a real low-memory situation, memwatch logs that
|
||||||
|
too. Memwatch itself has some reserve memory tucked away so
|
||||||
|
it should continue running even in the worst conditions.
|
||||||
|
|
||||||
|
Hunting down wild writes and other Nasty Things
|
||||||
|
|
||||||
|
Wild writes are usually caused by using pointers that arent
|
||||||
|
initialized, or that were initialized, but then the memory
|
||||||
|
they points to is moved or freed. The best way to avoid
|
||||||
|
these kind of problems is to ALWAYS initialize pointers to
|
||||||
|
NULL, and after freeing a memory buffer, setting all
|
||||||
|
pointers that pointed to it to NULL.
|
||||||
|
|
||||||
|
To aid in tracking down uninitialized pointers memwatch
|
||||||
|
zaps all memory with certain values. Recently allocated
|
||||||
|
memory (unless calloc'd, of course), contains 0xFE.
|
||||||
|
Recently freed memory contains 0xFD. So if your program
|
||||||
|
crashes when using memwatch and not without memwatch, it's
|
||||||
|
most likely because you are not initializing your allocated
|
||||||
|
buffers, or using the buffers after they've been freed.
|
||||||
|
|
||||||
|
In the event that a wild pointer should damage memwatch's
|
||||||
|
internal data structures, memwatch employs checksums,
|
||||||
|
multiple copies of some values, and can also repair it's
|
||||||
|
own data structures.
|
||||||
|
|
||||||
|
If you are a paranoid person, and as programmer you should
|
||||||
|
be, you can use memwatch's mwIsReadAddr() and
|
||||||
|
mwIsSafeAddr() functions to check the accessibility of
|
||||||
|
memory. These are implemented for both ANSI C systems and
|
||||||
|
Win32 systems. Just put an mwASSERT() around the check and
|
||||||
|
forget about it.
|
||||||
|
|
||||||
|
Can I help?
|
||||||
|
|
||||||
|
Well, sure. For instance, I like memwatch to compile
|
||||||
|
without any warnings or errors. If you are using an ANSI C
|
||||||
|
compliant compiler, and are getting warnings or errors,
|
||||||
|
please mail me the details and instructions on how to fix
|
||||||
|
them, if you can.
|
||||||
|
|
||||||
|
Another thing you can do if you decide to use memwatch is
|
||||||
|
to mail me the name of the project(s) (and URL, if any),
|
||||||
|
hardware and operating system, compiler and what user
|
||||||
|
(organization). I will then post this info on the list of
|
||||||
|
memwatch users.
|
||||||
|
(http://www.linkdata.se/memwatchusers.html)
|
||||||
|
|
||||||
|
Top five problems using memwatch
|
||||||
|
|
||||||
|
5. Passed a non-memwatch allocated pointer to memwatch's
|
||||||
|
free(). Symtom: Causes an erroneous "WILD free" log
|
||||||
|
entry to appear. Cure: Either include memwatch.h for
|
||||||
|
the file that allocates, or use mwFree_() to free it.
|
||||||
|
|
||||||
|
4. Relied on auto-initialization when using atexit().
|
||||||
|
Symptom: Causes incorrect "unfreed" and "WILD free"
|
||||||
|
messages. Cure: Use mwInit() and mwTerm().
|
||||||
|
|
||||||
|
3. Forgot to include memwatch.h in all files. Symptom:
|
||||||
|
Tends to generate "WILD free" and "unfreed" messages.
|
||||||
|
Cure: Make sure to include memwatch.h!
|
||||||
|
|
||||||
|
2. No write permissions in currect directory. Symptom:
|
||||||
|
Seems like memwatch 'just aint working'. Cure: Use
|
||||||
|
mwSetOutFunc() to redirect output.
|
||||||
|
|
||||||
|
...and the number one problem is...
|
||||||
|
|
||||||
|
1. Didn't define MEMWATCH when compiling. Symptom:
|
||||||
|
Memwatch dutifully disables itself. Cure: Try adding
|
||||||
|
-DMEMWATCH to the command line.
|
||||||
|
|
340
client/src/thirdparty/memwatch/gpl.txt
vendored
Normal file
340
client/src/thirdparty/memwatch/gpl.txt
vendored
Normal file
|
@ -0,0 +1,340 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program 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; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
2664
client/src/thirdparty/memwatch/memwatch.c
vendored
Normal file
2664
client/src/thirdparty/memwatch/memwatch.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
707
client/src/thirdparty/memwatch/memwatch.h
vendored
Normal file
707
client/src/thirdparty/memwatch/memwatch.h
vendored
Normal file
|
@ -0,0 +1,707 @@
|
||||||
|
/*
|
||||||
|
** MEMWATCH.H
|
||||||
|
** Nonintrusive ANSI C memory leak / overwrite detection
|
||||||
|
** Copyright (C) 1992-2002 Johan Lindh
|
||||||
|
** All rights reserved.
|
||||||
|
** Version 2.71
|
||||||
|
**
|
||||||
|
************************************************************************
|
||||||
|
**
|
||||||
|
** PURPOSE:
|
||||||
|
**
|
||||||
|
** MEMWATCH has been written to allow guys and gals that like to
|
||||||
|
** program in C a public-domain memory error control product.
|
||||||
|
** I hope you'll find it's as advanced as most commercial packages.
|
||||||
|
** The idea is that you use it during the development phase and
|
||||||
|
** then remove the MEMWATCH define to produce your final product.
|
||||||
|
** MEMWATCH is distributed in source code form in order to allow
|
||||||
|
** you to compile it for your platform with your own compiler.
|
||||||
|
** It's aim is to be 100% ANSI C, but some compilers are more stingy
|
||||||
|
** than others. If it doesn't compile without warnings, please mail
|
||||||
|
** me the configuration of operating system and compiler you are using
|
||||||
|
** along with a description of how to modify the source, and the version
|
||||||
|
** number of MEMWATCH that you are using.
|
||||||
|
**
|
||||||
|
************************************************************************
|
||||||
|
|
||||||
|
This file is part of MEMWATCH.
|
||||||
|
|
||||||
|
MEMWATCH 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; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
MEMWATCH 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 MEMWATCH; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
************************************************************************
|
||||||
|
**
|
||||||
|
** REVISION HISTORY:
|
||||||
|
**
|
||||||
|
** 920810 JLI [1.00]
|
||||||
|
** 920830 JLI [1.10 double-free detection]
|
||||||
|
** 920912 JLI [1.15 mwPuts, mwGrab/Drop, mwLimit]
|
||||||
|
** 921022 JLI [1.20 ASSERT and VERIFY]
|
||||||
|
** 921105 JLI [1.30 C++ support and TRACE]
|
||||||
|
** 921116 JLI [1.40 mwSetOutFunc]
|
||||||
|
** 930215 JLI [1.50 modified ASSERT/VERIFY]
|
||||||
|
** 930327 JLI [1.51 better auto-init & PC-lint support]
|
||||||
|
** 930506 JLI [1.55 MemWatch class, improved C++ support]
|
||||||
|
** 930507 JLI [1.60 mwTest & CHECK()]
|
||||||
|
** 930809 JLI [1.65 Abort/Retry/Ignore]
|
||||||
|
** 930820 JLI [1.70 data dump when unfreed]
|
||||||
|
** 931016 JLI [1.72 modified C++ new/delete handling]
|
||||||
|
** 931108 JLI [1.77 mwSetAssertAction() & some small changes]
|
||||||
|
** 940110 JLI [1.80 no-mans-land alloc/checking]
|
||||||
|
** 940328 JLI [2.00 version 2.0 rewrite]
|
||||||
|
** Improved NML (no-mans-land) support.
|
||||||
|
** Improved performance (especially for free()ing!).
|
||||||
|
** Support for 'read-only' buffers (checksums)
|
||||||
|
** ^^ NOTE: I never did this... maybe I should?
|
||||||
|
** FBI (free'd block info) tagged before freed blocks
|
||||||
|
** Exporting of the mwCounter variable
|
||||||
|
** mwBreakOut() localizes debugger support
|
||||||
|
** Allocation statistics (global, per-module, per-line)
|
||||||
|
** Self-repair ability with relinking
|
||||||
|
** 950913 JLI [2.10 improved garbage handling]
|
||||||
|
** 951201 JLI [2.11 improved auto-free in emergencies]
|
||||||
|
** 960125 JLI [X.01 implemented auto-checking using mwAutoCheck()]
|
||||||
|
** 960514 JLI [2.12 undefining of existing macros]
|
||||||
|
** 960515 JLI [2.13 possibility to use default new() & delete()]
|
||||||
|
** 960516 JLI [2.20 suppression of file flushing on unfreed msgs]
|
||||||
|
** 960516 JLI [2.21 better support for using MEMWATCH with DLL's]
|
||||||
|
** 960710 JLI [X.02 multiple logs and mwFlushNow()]
|
||||||
|
** 960801 JLI [2.22 merged X.01 version with current]
|
||||||
|
** 960805 JLI [2.30 mwIsXXXXAddr() to avoid unneeded GP's]
|
||||||
|
** 960805 JLI [2.31 merged X.02 version with current]
|
||||||
|
** 961002 JLI [2.32 support for realloc() + fixed STDERR bug]
|
||||||
|
** 961222 JLI [2.40 added mwMark() & mwUnmark()]
|
||||||
|
** 970101 JLI [2.41 added over/underflow checking after failed ASSERT/VERIFY]
|
||||||
|
** 970113 JLI [2.42 added support for PC-Lint 7.00g]
|
||||||
|
** 970207 JLI [2.43 added support for strdup()]
|
||||||
|
** 970209 JLI [2.44 changed default filename to lowercase]
|
||||||
|
** 970405 JLI [2.45 fixed bug related with atexit() and some C++ compilers]
|
||||||
|
** 970723 JLI [2.46 added MW_ARI_NULLREAD flag]
|
||||||
|
** 970813 JLI [2.47 stabilized marker handling]
|
||||||
|
** 980317 JLI [2.48 ripped out C++ support; wasn't working good anyway]
|
||||||
|
** 980318 JLI [2.50 improved self-repair facilities & SIGSEGV support]
|
||||||
|
** 980417 JLI [2.51 more checks for invalid addresses]
|
||||||
|
** 980512 JLI [2.52 moved MW_ARI_NULLREAD to occur before aborting]
|
||||||
|
** 990112 JLI [2.53 added check for empty heap to mwIsOwned]
|
||||||
|
** 990217 JLI [2.55 improved the emergency repairs diagnostics and NML]
|
||||||
|
** 990224 JLI [2.56 changed ordering of members in structures]
|
||||||
|
** 990303 JLI [2.57 first maybe-fixit-for-hpux test]
|
||||||
|
** 990516 JLI [2.58 added 'static' to the definition of mwAutoInit]
|
||||||
|
** 990517 JLI [2.59 fixed some high-sensitivity warnings]
|
||||||
|
** 990610 JLI [2.60 fixed some more high-sensitivity warnings]
|
||||||
|
** 990715 JLI [2.61 changed TRACE/ASSERT/VERIFY macro names]
|
||||||
|
** 991001 JLI [2.62 added CHECK_BUFFER() and mwTestBuffer()]
|
||||||
|
** 991007 JLI [2.63 first shot at a 64-bit compatible version]
|
||||||
|
** 991009 JLI [2.64 undef's strdup() if defined, mwStrdup made const]
|
||||||
|
** 000704 JLI [2.65 added some more detection for 64-bits]
|
||||||
|
** 010502 JLI [2.66 incorporated some user fixes]
|
||||||
|
** [mwRelink() could print out garbage pointer (thanks mac@phobos.ca)]
|
||||||
|
** [added array destructor for C++ (thanks rdasilva@connecttel.com)]
|
||||||
|
** [added mutex support (thanks rdasilva@connecttel.com)]
|
||||||
|
** 010531 JLI [2.67 fix: mwMutexXXX() was declared even if MW_HAVE_MUTEX was not defined]
|
||||||
|
** 010619 JLI [2.68 fix: mwRealloc() could leave the mutex locked]
|
||||||
|
** 020918 JLI [2.69 changed to GPL, added C++ array allocation by Howard Cohen]
|
||||||
|
** 030212 JLI [2.70 mwMalloc() bug for very large allocations (4GB on 32bits)]
|
||||||
|
** 030520 JLI [2.71 added ULONG_LONG_MAX as a 64-bit detector (thanks Sami Salonen)]
|
||||||
|
**
|
||||||
|
** To use, simply include 'MEMWATCH.H' as a header file,
|
||||||
|
** and add MEMWATCH.C to your list of files, and define the macro
|
||||||
|
** 'MEMWATCH'. If this is not defined, MEMWATCH will disable itself.
|
||||||
|
**
|
||||||
|
** To call the standard C malloc / realloc / calloc / free; use mwMalloc_(),
|
||||||
|
** mwCalloc_() and mwFree_(). Note that mwFree_() will correctly
|
||||||
|
** free both malloc()'d memory as well as mwMalloc()'d.
|
||||||
|
**
|
||||||
|
** 980317: C++ support has been disabled.
|
||||||
|
** The code remains, but is not compiled.
|
||||||
|
**
|
||||||
|
** For use with C++, which allows use of inlining in header files
|
||||||
|
** and class specific new/delete, you must also define 'new' as
|
||||||
|
** 'mwNew' and 'delete' as 'mwDelete'. Do this *after* you include
|
||||||
|
** C++ header files from libraries, otherwise you can mess up their
|
||||||
|
** class definitions. If you don't define these, the C++ allocations
|
||||||
|
** will not have source file and line number information. Also note,
|
||||||
|
** most C++ class libraries implement their own C++ memory management,
|
||||||
|
** and don't allow anyone to override them. MFC belongs to this crew.
|
||||||
|
** In these cases, the only thing to do is to use MEMWATCH_NOCPP.
|
||||||
|
**
|
||||||
|
** You can capture output from MEMWATCH using mwSetOutFunc().
|
||||||
|
** Just give it the adress of a "void myOutFunc(int c)" function,
|
||||||
|
** and all characters to be output will be redirected there.
|
||||||
|
**
|
||||||
|
** A failing ASSERT() or VERIFY() will normally always abort your
|
||||||
|
** program. This can be changed using mwSetAriFunc(). Give it a
|
||||||
|
** pointer to a "int myAriFunc(const char *)" function. Your function
|
||||||
|
** must ask the user whether to Abort, Retry or Ignore the trap.
|
||||||
|
** Return 2 to Abort, 1 to Retry or 0 to Ignore. Beware retry; it
|
||||||
|
** causes the expression to be evaluated again! MEMWATCH has a
|
||||||
|
** default ARI handler. It's disabled by default, but you can enable
|
||||||
|
** it by calling 'mwDefaultAri()'. Note that this will STILL abort
|
||||||
|
** your program unless you define MEMWATCH_STDIO to allow MEMWATCH
|
||||||
|
** to use the standard C I/O streams. Also, setting the ARI function
|
||||||
|
** will cause MEMWATCH *NOT* to write the ARI error to stderr. The
|
||||||
|
** error string is passed to the ARI function instead, as the
|
||||||
|
** 'const char *' parameter.
|
||||||
|
**
|
||||||
|
** You can disable MEMWATCH's ASSERT/VERIFY and/or TRACE implementations.
|
||||||
|
** This can be useful if you're using a debug terminal or smart debugger.
|
||||||
|
** Disable them by defining MW_NOASSERT, MW_NOVERIFY or MW_NOTRACE.
|
||||||
|
**
|
||||||
|
** MEMWATCH fills all allocated memory with the byte 0xFE, so if
|
||||||
|
** you're looking at erroneous data which are all 0xFE:s, the
|
||||||
|
** data probably was not initialized by you. The exception is
|
||||||
|
** calloc(), which will fill with zero's. All freed buffers are
|
||||||
|
** zapped with 0xFD. If this is what you look at, you're using
|
||||||
|
** data that has been freed. If this is the case, be aware that
|
||||||
|
** MEMWATCH places a 'free'd block info' structure immediately
|
||||||
|
** before the freed data. This block contains info about where
|
||||||
|
** the block was freed. The information is in readable text,
|
||||||
|
** in the format "FBI<counter>filename(line)", for example:
|
||||||
|
** "FBI<267>test.c(12)". Using FBI's slows down free(), so it's
|
||||||
|
** disabled by default. Use mwFreeBufferInfo(1) to enable it.
|
||||||
|
**
|
||||||
|
** To aid in tracking down wild pointer writes, MEMWATCH can perform
|
||||||
|
** no-mans-land allocations. No-mans-land will contain the byte 0xFC.
|
||||||
|
** MEMWATCH will, when this is enabled, convert recently free'd memory
|
||||||
|
** into NML allocations.
|
||||||
|
**
|
||||||
|
** MEMWATCH protects it's own data buffers with checksums. If you
|
||||||
|
** get an internal error, it means you're overwriting wildly,
|
||||||
|
** or using an uninitialized pointer.
|
||||||
|
**
|
||||||
|
************************************************************************
|
||||||
|
**
|
||||||
|
** Note when compiling with Microsoft C:
|
||||||
|
** - MSC ignores fflush() by default. This is overridden, so that
|
||||||
|
** the disk log will always be current.
|
||||||
|
**
|
||||||
|
** This utility has been tested with:
|
||||||
|
** PC-lint 7.0k, passed as 100% ANSI C compatible
|
||||||
|
** Microsoft Visual C++ on Win16 and Win32
|
||||||
|
** Microsoft C on DOS
|
||||||
|
** SAS C on an Amiga 500
|
||||||
|
** Gnu C on a PC running Red Hat Linux
|
||||||
|
** ...and using an (to me) unknown compiler on an Atari machine.
|
||||||
|
**
|
||||||
|
************************************************************************
|
||||||
|
**
|
||||||
|
** Format of error messages in MEMWATCH.LOG:
|
||||||
|
** message: <sequence-number> filename(linenumber), information
|
||||||
|
**
|
||||||
|
** Errors caught by MemWatch, when they are detected, and any
|
||||||
|
** actions taken besides writing to the log file MEMWATCH.LOG:
|
||||||
|
**
|
||||||
|
** Double-freeing:
|
||||||
|
** A pointer that was recently freed and has not since been
|
||||||
|
** reused was freed again. The place where the previous free()
|
||||||
|
** was executed is displayed.
|
||||||
|
** Detect: delete or free() using the offending pointer.
|
||||||
|
** Action: The delete or free() is cancelled, execution continues.
|
||||||
|
** Underflow:
|
||||||
|
** You have written just ahead of the allocated memory.
|
||||||
|
** The size and place of the allocation is displayed.
|
||||||
|
** Detect: delete or free() of the damaged buffer.
|
||||||
|
** Action: The buffer is freed, but there may be secondary damage.
|
||||||
|
** Overflow:
|
||||||
|
** Like underflow, but you've written after the end of the buffer.
|
||||||
|
** Detect: see Underflow.
|
||||||
|
** Action: see Underflow.
|
||||||
|
** WILD free:
|
||||||
|
** An unrecognized pointer was passed to delete or free().
|
||||||
|
** The pointer may have been returned from a library function;
|
||||||
|
** in that case, use mwFree_() to force free() of it.
|
||||||
|
** Also, this may be a double-free, but the previous free was
|
||||||
|
** too long ago, causing MEMWATCH to 'forget' it.
|
||||||
|
** Detect: delete or free() of the offending pointer.
|
||||||
|
** Action: The delete or free() is cancelled, execution continues.
|
||||||
|
** NULL free:
|
||||||
|
** It's unclear to me whether or not freeing of NULL pointers
|
||||||
|
** is legal in ANSI C, therefore a warning is written to the log file,
|
||||||
|
** but the error counter remains the same. This is legal using C++,
|
||||||
|
** so the warning does not appear with delete.
|
||||||
|
** Detect: When you free(NULL).
|
||||||
|
** Action: The free() is cancelled.
|
||||||
|
** Failed:
|
||||||
|
** A request to allocate memory failed. If the allocation is
|
||||||
|
** small, this may be due to memory depletion, but is more likely
|
||||||
|
** to be memory fragmentation problems. The amount of memory
|
||||||
|
** allocated so far is displayed also.
|
||||||
|
** Detect: When you new, malloc(), realloc() or calloc() memory.
|
||||||
|
** Action: NULL is returned.
|
||||||
|
** Realloc:
|
||||||
|
** A request to re-allocate a memory buffer failed for reasons
|
||||||
|
** other than out-of-memory. The specific reason is shown.
|
||||||
|
** Detect: When you realloc()
|
||||||
|
** Action: realloc() is cancelled, NULL is returned
|
||||||
|
** Limit fail:
|
||||||
|
** A request to allocate memory failed since it would violate
|
||||||
|
** the limit set using mwLimit(). mwLimit() is used to stress-test
|
||||||
|
** your code under simulated low memory conditions.
|
||||||
|
** Detect: At new, malloc(), realloc() or calloc().
|
||||||
|
** Action: NULL is returned.
|
||||||
|
** Assert trap:
|
||||||
|
** An ASSERT() failed. The ASSERT() macro works like C's assert()
|
||||||
|
** macro/function, except that it's interactive. See your C manual.
|
||||||
|
** Detect: On the ASSERT().
|
||||||
|
** Action: Program ends with an advisory message to stderr, OR
|
||||||
|
** Program writes the ASSERT to the log and continues, OR
|
||||||
|
** Program asks Abort/Retry/Ignore? and takes that action.
|
||||||
|
** Verify trap:
|
||||||
|
** A VERIFY() failed. The VERIFY() macro works like ASSERT(),
|
||||||
|
** but if MEMWATCH is not defined, it still evaluates the
|
||||||
|
** expression, but it does not act upon the result.
|
||||||
|
** Detect: On the VERIFY().
|
||||||
|
** Action: Program ends with an advisory message to stderr, OR
|
||||||
|
** Program writes the VERIFY to the log and continues, OR
|
||||||
|
** Program asks Abort/Retry/Ignore? and takes that action.
|
||||||
|
** Wild pointer:
|
||||||
|
** A no-mans-land buffer has been written into. MEMWATCH can
|
||||||
|
** allocate and distribute chunks of memory solely for the
|
||||||
|
** purpose of trying to catch random writes into memory.
|
||||||
|
** Detect: Always on CHECK(), but can be detected in several places.
|
||||||
|
** Action: The error is logged, and if an ARI handler is installed,
|
||||||
|
** it is executed, otherwise, execution continues.
|
||||||
|
** Unfreed:
|
||||||
|
** A memory buffer you allocated has not been freed.
|
||||||
|
** You are informed where it was allocated, and whether any
|
||||||
|
** over or underflow has occured. MemWatch also displays up to
|
||||||
|
** 16 bytes of the data, as much as it can, in hex and text.
|
||||||
|
** Detect: When MemWatch terminates.
|
||||||
|
** Action: The buffer is freed.
|
||||||
|
** Check:
|
||||||
|
** An error was detected during a CHECK() operation.
|
||||||
|
** The associated pointer is displayed along with
|
||||||
|
** the file and line where the CHECK() was executed.
|
||||||
|
** Followed immediately by a normal error message.
|
||||||
|
** Detect: When you CHECK()
|
||||||
|
** Action: Depends on the error
|
||||||
|
** Relink:
|
||||||
|
** After a MEMWATCH internal control block has been trashed,
|
||||||
|
** MEMWATCH tries to repair the damage. If successful, program
|
||||||
|
** execution will continue instead of aborting. Some information
|
||||||
|
** about the block may be gone permanently, though.
|
||||||
|
** Detect: N/A
|
||||||
|
** Action: Relink successful: program continues.
|
||||||
|
** Relink fails: program aborts.
|
||||||
|
** Internal:
|
||||||
|
** An internal error is flagged by MEMWATCH when it's control
|
||||||
|
** structures have been damaged. You are likely using an uninitialized
|
||||||
|
** pointer somewhere in your program, or are zapping memory all over.
|
||||||
|
** The message may give you additional diagnostic information.
|
||||||
|
** If possible, MEMWATCH will recover and continue execution.
|
||||||
|
** Detect: Various actions.
|
||||||
|
** Action: Whatever is needed
|
||||||
|
** Mark:
|
||||||
|
** The program terminated without umarking all marked pointers. Marking
|
||||||
|
** can be used to track resources other than memory. mwMark(pointer,text,...)
|
||||||
|
** when the resource is allocated, and mwUnmark(pointer) when it's freed.
|
||||||
|
** The 'text' is displayed for still marked pointers when the program
|
||||||
|
** ends.
|
||||||
|
** Detect: When MemWatch terminates.
|
||||||
|
** Action: The error is logged.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
************************************************************************
|
||||||
|
**
|
||||||
|
** The author may be reached by e-mail at the address below. If you
|
||||||
|
** mail me about source code changes in MEMWATCH, remember to include
|
||||||
|
** MW's version number.
|
||||||
|
**
|
||||||
|
** Johan Lindh
|
||||||
|
** johan@linkdata.se
|
||||||
|
**
|
||||||
|
** The latest version of MEMWATCH may be downloaded from
|
||||||
|
** http://www.linkdata.se/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MEMWATCH_H
|
||||||
|
#define __MEMWATCH_H
|
||||||
|
|
||||||
|
/* Make sure that malloc(), realloc(), calloc() and free() are declared. */
|
||||||
|
/*lint -save -e537 */
|
||||||
|
#include <stdlib.h>
|
||||||
|
/*lint -restore */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Constants used
|
||||||
|
** All MEMWATCH constants start with the prefix MW_, followed by
|
||||||
|
** a short mnemonic which indicates where the constant is used,
|
||||||
|
** followed by a descriptive text about it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MW_ARI_NULLREAD 0x10 /* Null read (to start debugger) */
|
||||||
|
#define MW_ARI_ABORT 0x04 /* ARI handler says: abort program! */
|
||||||
|
#define MW_ARI_RETRY 0x02 /* ARI handler says: retry action! */
|
||||||
|
#define MW_ARI_IGNORE 0x01 /* ARI handler says: ignore error! */
|
||||||
|
|
||||||
|
#define MW_VAL_NEW 0xFE /* value in newly allocated memory */
|
||||||
|
#define MW_VAL_DEL 0xFD /* value in newly deleted memory */
|
||||||
|
#define MW_VAL_NML 0xFC /* value in no-mans-land */
|
||||||
|
#define MW_VAL_GRB 0xFB /* value in grabbed memory */
|
||||||
|
|
||||||
|
#define MW_TEST_ALL 0xFFFF /* perform all tests */
|
||||||
|
#define MW_TEST_CHAIN 0x0001 /* walk the heap chain */
|
||||||
|
#define MW_TEST_ALLOC 0x0002 /* test allocations & NML guards */
|
||||||
|
#define MW_TEST_NML 0x0004 /* test all-NML areas for modifications */
|
||||||
|
|
||||||
|
#define MW_NML_NONE 0 /* no NML */
|
||||||
|
#define MW_NML_FREE 1 /* turn FREE'd memory into NML */
|
||||||
|
#define MW_NML_ALL 2 /* all unused memory is NML */
|
||||||
|
#define MW_NML_DEFAULT 0 /* the default NML setting */
|
||||||
|
|
||||||
|
#define MW_STAT_GLOBAL 0 /* only global statistics collected */
|
||||||
|
#define MW_STAT_MODULE 1 /* collect statistics on a module basis */
|
||||||
|
#define MW_STAT_LINE 2 /* collect statistics on a line basis */
|
||||||
|
#define MW_STAT_DEFAULT 0 /* the default statistics setting */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** MemWatch internal constants
|
||||||
|
** You may change these and recompile MemWatch to change the limits
|
||||||
|
** of some parameters. Respect the recommended minimums!
|
||||||
|
*/
|
||||||
|
#define MW_TRACE_BUFFER 2048 /* (min 160) size of TRACE()'s output buffer */
|
||||||
|
#define MW_FREE_LIST 64 /* (min 4) number of free()'s to track */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Exported variables
|
||||||
|
** In case you have to remove the 'const' keyword because your compiler
|
||||||
|
** doesn't support it, be aware that changing the values may cause
|
||||||
|
** unpredictable behaviour.
|
||||||
|
** - mwCounter contains the current action count. You can use this to
|
||||||
|
** place breakpoints using a debugger, if you want.
|
||||||
|
*/
|
||||||
|
#ifndef __MEMWATCH_C
|
||||||
|
extern const unsigned long mwCounter;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** System functions
|
||||||
|
** Normally, it is not nessecary to call any of these. MEMWATCH will
|
||||||
|
** automatically initialize itself on the first MEMWATCH function call,
|
||||||
|
** and set up a call to mwAbort() using atexit(). Some C++ implementations
|
||||||
|
** run the atexit() chain before the program has terminated, so you
|
||||||
|
** may have to use mwInit() or the MemWatch C++ class to get good
|
||||||
|
** behaviour.
|
||||||
|
** - mwInit() can be called to disable the atexit() usage. If mwInit()
|
||||||
|
** is called directly, you must call mwTerm() to end MemWatch, or
|
||||||
|
** mwAbort().
|
||||||
|
** - mwTerm() is usually not nessecary to call; but if called, it will
|
||||||
|
** call mwAbort() if it finds that it is cancelling the 'topmost'
|
||||||
|
** mwInit() call.
|
||||||
|
** - mwAbort() cleans up after MEMWATCH, reports unfreed buffers, etc.
|
||||||
|
*/
|
||||||
|
void mwInit( void );
|
||||||
|
void mwTerm( void );
|
||||||
|
void mwAbort( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Setup functions
|
||||||
|
** These functions control the operation of MEMWATCH's protective features.
|
||||||
|
** - mwFlushNow() causes MEMWATCH to flush it's buffers.
|
||||||
|
** - mwDoFlush() controls whether MEMWATCH flushes the disk buffers after
|
||||||
|
** writes. The default is smart flushing: MEMWATCH will not flush buffers
|
||||||
|
** explicitly until memory errors are detected. Then, all writes are
|
||||||
|
** flushed until program end or mwDoFlush(0) is called.
|
||||||
|
** - mwLimit() sets the allocation limit, an arbitrary limit on how much
|
||||||
|
** memory your program may allocate in bytes. Used to stress-test app.
|
||||||
|
** Also, in virtual-memory or multitasking environs, puts a limit on
|
||||||
|
** how much MW_NML_ALL can eat up.
|
||||||
|
** - mwGrab() grabs up X kilobytes of memory. Allocates actual memory,
|
||||||
|
** can be used to stress test app & OS both.
|
||||||
|
** - mwDrop() drops X kilobytes of grabbed memory.
|
||||||
|
** - mwNoMansLand() sets the behaviour of the NML logic. See the
|
||||||
|
** MW_NML_xxx for more information. The default is MW_NML_DEFAULT.
|
||||||
|
** - mwStatistics() sets the behaviour of the statistics collector. See
|
||||||
|
** the MW_STAT_xxx defines for more information. Default MW_STAT_DEFAULT.
|
||||||
|
** - mwFreeBufferInfo() enables or disables the tagging of free'd buffers
|
||||||
|
** with freeing information. This information is written in text form,
|
||||||
|
** using sprintf(), so it's pretty slow. Disabled by default.
|
||||||
|
** - mwAutoCheck() performs a CHECK() operation whenever a MemWatch function
|
||||||
|
** is used. Slows down performance, of course.
|
||||||
|
** - mwCalcCheck() calculates checksums for all data buffers. Slow!
|
||||||
|
** - mwDumpCheck() logs buffers where stored & calc'd checksums differ. Slow!!
|
||||||
|
** - mwMark() sets a generic marker. Returns the pointer given.
|
||||||
|
** - mwUnmark() removes a generic marker. If, at the end of execution, some
|
||||||
|
** markers are still in existence, these will be reported as leakage.
|
||||||
|
** returns the pointer given.
|
||||||
|
*/
|
||||||
|
void mwFlushNow( void );
|
||||||
|
void mwDoFlush( int onoff );
|
||||||
|
void mwLimit( long bytes );
|
||||||
|
unsigned mwGrab( unsigned kilobytes );
|
||||||
|
unsigned mwDrop( unsigned kilobytes );
|
||||||
|
void mwNoMansLand( int mw_nml_level );
|
||||||
|
void mwStatistics( int level );
|
||||||
|
void mwFreeBufferInfo( int onoff );
|
||||||
|
void mwAutoCheck( int onoff );
|
||||||
|
void mwCalcCheck( void );
|
||||||
|
void mwDumpCheck( void );
|
||||||
|
void * mwMark( void *p, const char *description, const char *file, unsigned line );
|
||||||
|
void * mwUnmark( void *p, const char *file, unsigned line );
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Testing/verification/tracing
|
||||||
|
** All of these macros except VERIFY() evaluates to a null statement
|
||||||
|
** if MEMWATCH is not defined during compilation.
|
||||||
|
** - mwIsReadAddr() checks a memory area for read privilige.
|
||||||
|
** - mwIsSafeAddr() checks a memory area for both read & write privilige.
|
||||||
|
** This function and mwIsReadAddr() is highly system-specific and
|
||||||
|
** may not be implemented. If this is the case, they will default
|
||||||
|
** to returning nonzero for any non-NULL pointer.
|
||||||
|
** - CHECK() does a complete memory integrity test. Slow!
|
||||||
|
** - CHECK_THIS() checks only selected components.
|
||||||
|
** - CHECK_BUFFER() checks the indicated buffer for errors.
|
||||||
|
** - mwASSERT() or ASSERT() If the expression evaluates to nonzero, execution continues.
|
||||||
|
** Otherwise, the ARI handler is called, if present. If not present,
|
||||||
|
** the default ARI action is taken (set with mwSetAriAction()).
|
||||||
|
** ASSERT() can be disabled by defining MW_NOASSERT.
|
||||||
|
** - mwVERIFY() or VERIFY() works just like ASSERT(), but when compiling without
|
||||||
|
** MEMWATCH the macro evaluates to the expression.
|
||||||
|
** VERIFY() can be disabled by defining MW_NOVERIFY.
|
||||||
|
** - mwTRACE() or TRACE() writes some text and data to the log. Use like printf().
|
||||||
|
** TRACE() can be disabled by defining MW_NOTRACE.
|
||||||
|
*/
|
||||||
|
int mwIsReadAddr( const void *p, unsigned len );
|
||||||
|
int mwIsSafeAddr( void *p, unsigned len );
|
||||||
|
int mwTest( const char *file, int line, int mw_test_flags );
|
||||||
|
int mwTestBuffer( const char *file, int line, void *p );
|
||||||
|
int mwAssert( int, const char*, const char*, int );
|
||||||
|
int mwVerify( int, const char*, const char*, int );
|
||||||
|
|
||||||
|
/*
|
||||||
|
** User I/O functions
|
||||||
|
** - mwTrace() works like printf(), but dumps output either to the
|
||||||
|
** function specified with mwSetOutFunc(), or the log file.
|
||||||
|
** - mwPuts() works like puts(), dumps output like mwTrace().
|
||||||
|
** - mwSetOutFunc() allows you to give the adress of a function
|
||||||
|
** where all user output will go. (exeption: see mwSetAriFunc)
|
||||||
|
** Specifying NULL will direct output to the log file.
|
||||||
|
** - mwSetAriFunc() gives MEMWATCH the adress of a function to call
|
||||||
|
** when an 'Abort, Retry, Ignore' question is called for. The
|
||||||
|
** actual error message is NOT printed when you've set this adress,
|
||||||
|
** but instead it is passed as an argument. If you call with NULL
|
||||||
|
** for an argument, the ARI handler is disabled again. When the
|
||||||
|
** handler is disabled, MEMWATCH will automatically take the
|
||||||
|
** action specified by mwSetAriAction().
|
||||||
|
** - mwSetAriAction() sets the default ARI return value MEMWATCH should
|
||||||
|
** use if no ARI handler is specified. Defaults to MW_ARI_ABORT.
|
||||||
|
** - mwAriHandler() is an ANSI ARI handler you can use if you like. It
|
||||||
|
** dumps output to stderr, and expects input from stdin.
|
||||||
|
** - mwBreakOut() is called in certain cases when MEMWATCH feels it would
|
||||||
|
** be nice to break into a debugger. If you feel like MEMWATCH, place
|
||||||
|
** an execution breakpoint on this function.
|
||||||
|
*/
|
||||||
|
void mwTrace( const char* format_string, ... );
|
||||||
|
void mwPuts( const char* text );
|
||||||
|
void mwSetOutFunc( void (*func)(int) );
|
||||||
|
void mwSetAriFunc( int (*func)(const char*) );
|
||||||
|
void mwSetAriAction( int mw_ari_value );
|
||||||
|
int mwAriHandler( const char* cause );
|
||||||
|
void mwBreakOut( const char* cause );
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Allocation/deallocation functions
|
||||||
|
** These functions are the ones actually to perform allocations
|
||||||
|
** when running MEMWATCH, for both C and C++ calls.
|
||||||
|
** - mwMalloc() debugging allocator
|
||||||
|
** - mwMalloc_() always resolves to a clean call of malloc()
|
||||||
|
** - mwRealloc() debugging re-allocator
|
||||||
|
** - mwRealloc_() always resolves to a clean call of realloc()
|
||||||
|
** - mwCalloc() debugging allocator, fills with zeros
|
||||||
|
** - mwCalloc_() always resolves to a clean call of calloc()
|
||||||
|
** - mwFree() debugging free. Can only free memory which has
|
||||||
|
** been allocated by MEMWATCH.
|
||||||
|
** - mwFree_() resolves to a) normal free() or b) debugging free.
|
||||||
|
** Can free memory allocated by MEMWATCH and malloc() both.
|
||||||
|
** Does not generate any runtime errors.
|
||||||
|
*/
|
||||||
|
void* mwMalloc( size_t, const char*, int );
|
||||||
|
void* mwMalloc_( size_t );
|
||||||
|
void* mwRealloc( void *, size_t, const char*, int );
|
||||||
|
void* mwRealloc_( void *, size_t );
|
||||||
|
void* mwCalloc( size_t, size_t, const char*, int );
|
||||||
|
void* mwCalloc_( size_t, size_t );
|
||||||
|
void mwFree( void*, const char*, int );
|
||||||
|
void mwFree_( void* );
|
||||||
|
char* mwStrdup( const char *, const char*, int );
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Enable/disable precompiler block
|
||||||
|
** This block of defines and if(n)defs make sure that references
|
||||||
|
** to MEMWATCH is completely removed from the code if the MEMWATCH
|
||||||
|
** manifest constant is not defined.
|
||||||
|
*/
|
||||||
|
#ifndef __MEMWATCH_C
|
||||||
|
#ifdef MEMWATCH
|
||||||
|
|
||||||
|
#define mwASSERT(exp) while(mwAssert((int)(exp),#exp,__FILE__,__LINE__))
|
||||||
|
#ifndef MW_NOASSERT
|
||||||
|
#ifndef ASSERT
|
||||||
|
#define ASSERT mwASSERT
|
||||||
|
#endif /* !ASSERT */
|
||||||
|
#endif /* !MW_NOASSERT */
|
||||||
|
#define mwVERIFY(exp) while(mwVerify((int)(exp),#exp,__FILE__,__LINE__))
|
||||||
|
#ifndef MW_NOVERIFY
|
||||||
|
#ifndef VERIFY
|
||||||
|
#define VERIFY mwVERIFY
|
||||||
|
#endif /* !VERIFY */
|
||||||
|
#endif /* !MW_NOVERIFY */
|
||||||
|
#define mwTRACE mwTrace
|
||||||
|
#ifndef MW_NOTRACE
|
||||||
|
#ifndef TRACE
|
||||||
|
#define TRACE mwTRACE
|
||||||
|
#endif /* !TRACE */
|
||||||
|
#endif /* !MW_NOTRACE */
|
||||||
|
|
||||||
|
/* some compilers use a define and not a function */
|
||||||
|
/* for strdup(). */
|
||||||
|
#ifdef strdup
|
||||||
|
#undef strdup
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define malloc(n) mwMalloc(n,__FILE__,__LINE__)
|
||||||
|
#define strdup(p) mwStrdup(p,__FILE__,__LINE__)
|
||||||
|
#define realloc(p,n) mwRealloc(p,n,__FILE__,__LINE__)
|
||||||
|
#define calloc(n,m) mwCalloc(n,m,__FILE__,__LINE__)
|
||||||
|
#define free(p) mwFree(p,__FILE__,__LINE__)
|
||||||
|
#define CHECK() mwTest(__FILE__,__LINE__,MW_TEST_ALL)
|
||||||
|
#define CHECK_THIS(n) mwTest(__FILE__,__LINE__,n)
|
||||||
|
#define CHECK_BUFFER(b) mwTestBuffer(__FILE__,__LINE__,b)
|
||||||
|
#define MARK(p) mwMark(p,#p,__FILE__,__LINE__)
|
||||||
|
#define UNMARK(p) mwUnmark(p,__FILE__,__LINE__)
|
||||||
|
|
||||||
|
#else /* MEMWATCH */
|
||||||
|
|
||||||
|
#define mwASSERT(exp)
|
||||||
|
#ifndef MW_NOASSERT
|
||||||
|
#ifndef ASSERT
|
||||||
|
#define ASSERT mwASSERT
|
||||||
|
#endif /* !ASSERT */
|
||||||
|
#endif /* !MW_NOASSERT */
|
||||||
|
|
||||||
|
#define mwVERIFY(exp) exp
|
||||||
|
#ifndef MW_NOVERIFY
|
||||||
|
#ifndef VERIFY
|
||||||
|
#define VERIFY mwVERIFY
|
||||||
|
#endif /* !VERIFY */
|
||||||
|
#endif /* !MW_NOVERIFY */
|
||||||
|
|
||||||
|
/*lint -esym(773,mwTRACE) */
|
||||||
|
#define mwTRACE /*lint -save -e506 */ 1?(void)0:mwDummyTraceFunction /*lint -restore */
|
||||||
|
#ifndef MW_NOTRACE
|
||||||
|
#ifndef TRACE
|
||||||
|
/*lint -esym(773,TRACE) */
|
||||||
|
#define TRACE mwTRACE
|
||||||
|
#endif /* !TRACE */
|
||||||
|
#endif /* !MW_NOTRACE */
|
||||||
|
|
||||||
|
extern void mwDummyTraceFunction(const char *,...);
|
||||||
|
/*lint -save -e652 */
|
||||||
|
#define mwDoFlush(n)
|
||||||
|
#define mwPuts(s)
|
||||||
|
#define mwInit()
|
||||||
|
#define mwGrab(n)
|
||||||
|
#define mwDrop(n)
|
||||||
|
#define mwLimit(n)
|
||||||
|
#define mwTest(f,l)
|
||||||
|
#define mwSetOutFunc(f)
|
||||||
|
#define mwSetAriFunc(f)
|
||||||
|
#define mwDefaultAri()
|
||||||
|
#define mwNomansland()
|
||||||
|
#define mwStatistics(f)
|
||||||
|
#define mwMark(p,t,f,n) (p)
|
||||||
|
#define mwUnmark(p,f,n) (p)
|
||||||
|
#define mwMalloc(n,f,l) malloc(n)
|
||||||
|
#define mwStrdup(p,f,l) strdup(p)
|
||||||
|
#define mwRealloc(p,n,f,l) realloc(p,n)
|
||||||
|
#define mwCalloc(n,m,f,l) calloc(n,m)
|
||||||
|
#define mwFree(p) free(p)
|
||||||
|
#define mwMalloc_(n) malloc(n)
|
||||||
|
#define mwRealloc_(p,n) realloc(p,n)
|
||||||
|
#define mwCalloc_(n,m) calloc(n,m)
|
||||||
|
#define mwFree_(p) free(p)
|
||||||
|
#define mwAssert(e,es,f,l)
|
||||||
|
#define mwVerify(e,es,f,l) (e)
|
||||||
|
#define mwTrace mwDummyTrace
|
||||||
|
#define mwTestBuffer(f,l,b) (0)
|
||||||
|
#define CHECK()
|
||||||
|
#define CHECK_THIS(n)
|
||||||
|
#define CHECK_BUFFER(b)
|
||||||
|
#define MARK(p) (p)
|
||||||
|
#define UNMARK(p) (p)
|
||||||
|
/*lint -restore */
|
||||||
|
|
||||||
|
#endif /* MEMWATCH */
|
||||||
|
#endif /* !__MEMWATCH_C */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 /* 980317: disabled C++ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** C++ support section
|
||||||
|
** Implements the C++ support. Please note that in order to avoid
|
||||||
|
** messing up library classes, C++ support is disabled by default.
|
||||||
|
** You must NOT enable it until AFTER the inclusion of all header
|
||||||
|
** files belonging to code that are not compiled with MEMWATCH, and
|
||||||
|
** possibly for some that are! The reason for this is that a C++
|
||||||
|
** class may implement it's own new() function, and the preprocessor
|
||||||
|
** would substitute this crucial declaration for MEMWATCH new().
|
||||||
|
** You can forcibly deny C++ support by defining MEMWATCH_NOCPP.
|
||||||
|
** To enble C++ support, you must be compiling C++, MEMWATCH must
|
||||||
|
** be defined, MEMWATCH_NOCPP must not be defined, and finally,
|
||||||
|
** you must define 'new' to be 'mwNew', and 'delete' to be 'mwDelete'.
|
||||||
|
** Unlike C, C++ code can begin executing *way* before main(), for
|
||||||
|
** example if a global variable is created. For this reason, you can
|
||||||
|
** declare a global variable of the class 'MemWatch'. If this is
|
||||||
|
** is the first variable created, it will then check ALL C++ allocations
|
||||||
|
** and deallocations. Unfortunately, this evaluation order is not
|
||||||
|
** guaranteed by C++, though the compilers I've tried evaluates them
|
||||||
|
** in the order encountered.
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#ifndef __MEMWATCH_C
|
||||||
|
#ifdef MEMWATCH
|
||||||
|
#ifndef MEMWATCH_NOCPP
|
||||||
|
extern int mwNCur;
|
||||||
|
extern const char *mwNFile;
|
||||||
|
extern int mwNLine;
|
||||||
|
class MemWatch {
|
||||||
|
public:
|
||||||
|
MemWatch();
|
||||||
|
~MemWatch();
|
||||||
|
};
|
||||||
|
void * operator new(size_t);
|
||||||
|
void * operator new(size_t,const char *,int);
|
||||||
|
void * operator new[] (size_t,const char *,int); // hjc 07/16/02
|
||||||
|
void operator delete(void *);
|
||||||
|
#define mwNew new(__FILE__,__LINE__)
|
||||||
|
#define mwDelete (mwNCur=1,mwNFile=__FILE__,mwNLine=__LINE__),delete
|
||||||
|
#endif /* MEMWATCH_NOCPP */
|
||||||
|
#endif /* MEMWATCH */
|
||||||
|
#endif /* !__MEMWATCH_C */
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* 980317: disabled C++ */
|
||||||
|
|
||||||
|
#endif /* __MEMWATCH_H */
|
||||||
|
|
||||||
|
/* EOF MEMWATCH.H */
|
15
client/src/thirdparty/memwatch/memwatch.lsm
vendored
Normal file
15
client/src/thirdparty/memwatch/memwatch.lsm
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
Begin3
|
||||||
|
Title: memwatch
|
||||||
|
Version: 2.71
|
||||||
|
Entered-date: 2002-09-18
|
||||||
|
Description: fault tolerant ANSI-C source code memory leak and corruption detection
|
||||||
|
Keywords: memwatch debugging library memory leak source code ansi c
|
||||||
|
Author: johan@linkdata.se
|
||||||
|
Maintained-by: johan@linkdata.se
|
||||||
|
Primary-site: ftp.linkdata.se /pub/memwatch
|
||||||
|
42K memwatch-2.71.tar.gz
|
||||||
|
Alternate-site:
|
||||||
|
Original-site: ftp.linkdata.se /pub/memwatch
|
||||||
|
Platforms: all
|
||||||
|
Copying-policy: GPL
|
||||||
|
End
|
116
client/src/thirdparty/memwatch/test.c
vendored
Normal file
116
client/src/thirdparty/memwatch/test.c
vendored
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
** NOTE: Running this program in a Win32 or Unix environment
|
||||||
|
** will probably result in a segmentation fault or protection
|
||||||
|
** error. These errors may be caused by MEMWATCH when it is
|
||||||
|
** looking at memory to see if it owns it, or may be caused by
|
||||||
|
** the test program writing to memory it does not own.
|
||||||
|
**
|
||||||
|
** MEMWATCH has two functions called 'mwIsReadAddr()' and
|
||||||
|
** 'mwIsSafeAddr()', which are system-specific.
|
||||||
|
** If they are implemented for your system, and works
|
||||||
|
** correctly, MEMWATCH will identify garbage pointers and
|
||||||
|
** avoid causing segmentation faults, GP's etc.
|
||||||
|
**
|
||||||
|
** If they are NOT implemented, count on getting the core
|
||||||
|
** dumped when running this test program! As of this writing,
|
||||||
|
** the safe-address checking has been implemented for Win32
|
||||||
|
** and ANSI-C compliant systems. The ANSI-C checking traps
|
||||||
|
** SIGSEGV and uses setjmp/longjmp to resume processing.
|
||||||
|
**
|
||||||
|
** Note for Win95 users: The Win32 IsBadReadPtr() and its
|
||||||
|
** similar functions can return incorrect values. This has
|
||||||
|
** not happened under WinNT, though, just Win95.
|
||||||
|
**
|
||||||
|
** 991009 Johan Lindh
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include "memwatch.h"
|
||||||
|
|
||||||
|
#ifndef SIGSEGV
|
||||||
|
#error "SIGNAL.H does not define SIGSEGV; running this program WILL cause a core dump/crash!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MEMWATCH
|
||||||
|
#error "You really, really don't want to run this without memwatch. Trust me."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(MW_STDIO) && !defined(MEMWATCH_STDIO)
|
||||||
|
#error "Define MW_STDIO and try again, please."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
/* Collect stats on a line number basis */
|
||||||
|
mwStatistics( 2 );
|
||||||
|
|
||||||
|
/* Slows things down, but OK for this test prg */
|
||||||
|
/* mwAutoCheck( 1 ); */
|
||||||
|
|
||||||
|
TRACE("Hello world!\n");
|
||||||
|
|
||||||
|
p = malloc(210);
|
||||||
|
free(p);
|
||||||
|
p = malloc(20);
|
||||||
|
p = malloc(200); /* causes unfreed error */
|
||||||
|
p[-1] = 0; /* causes underflow error */
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
p = malloc(100);
|
||||||
|
p[ -(int)(sizeof(long)*8) ] = -1; /* try to damage MW's heap chain */
|
||||||
|
free( p ); /* should cause relink */
|
||||||
|
|
||||||
|
mwSetAriFunc( mwAriHandler );
|
||||||
|
ASSERT(1==2);
|
||||||
|
|
||||||
|
mwLimit(1000000);
|
||||||
|
mwNoMansLand( MW_NML_ALL );
|
||||||
|
|
||||||
|
/* These may cause a general protection fault (segmentation fault) */
|
||||||
|
/* They're here to help test the no-mans-land protection */
|
||||||
|
if( mwIsSafeAddr(p+50000,1) ) {
|
||||||
|
TRACE("Killing byte at %p\n", p+50000);
|
||||||
|
*(p+50000) = 0;
|
||||||
|
}
|
||||||
|
if( mwIsSafeAddr(p+30000,1) ) {
|
||||||
|
TRACE("Killing byte at %p\n", p+30000);
|
||||||
|
*(p+30000) = 0;
|
||||||
|
}
|
||||||
|
if( mwIsSafeAddr(p+1000,1) ) {
|
||||||
|
TRACE("Killing byte at %p\n", p+1000);
|
||||||
|
*(p+1000) = 0;
|
||||||
|
}
|
||||||
|
if( mwIsSafeAddr(p-100,1) ) {
|
||||||
|
TRACE("Killing byte at %p\n", p-100);
|
||||||
|
*(p-100) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This may cause a GP fault as well, since MW data buffers */
|
||||||
|
/* have been damaged in the above killing spree */
|
||||||
|
CHECK();
|
||||||
|
|
||||||
|
p = malloc(12000);
|
||||||
|
p[-5] = 1;
|
||||||
|
p[-10] = 2;
|
||||||
|
p[-15] = 3;
|
||||||
|
p[-20] = 4;
|
||||||
|
|
||||||
|
/* This may cause a GP fault since MW's buffer list may have */
|
||||||
|
/* been damaged by above killing, and it will try to repair it. */
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
p = realloc(p,10); /* causes realloc: free'd from error */
|
||||||
|
|
||||||
|
/* May cause GP since MW will inspect the memory to see if it owns it. */
|
||||||
|
free( (void*)main );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Comment out the following line to compile. */
|
||||||
|
#error "Hey! Don't just compile this program, read the comments first!"
|
2
client/src/thirdparty/stb_image.h
vendored
2
client/src/thirdparty/stb_image.h
vendored
|
@ -678,7 +678,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
|
||||||
#ifndef STBI_MALLOC
|
#ifndef STBI_MALLOC
|
||||||
#define STBI_MALLOC(sz) malloc(sz)
|
#define STBI_MALLOC(sz) malloc(sz)
|
||||||
#define STBI_REALLOC(p,newsz) realloc(p,newsz)
|
#define STBI_REALLOC(p,newsz) realloc(p,newsz)
|
||||||
#define STBI_FREE(p) free(p)
|
#define STBI_FREE(p) if (p) free(p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STBI_REALLOC_SIZED
|
#ifndef STBI_REALLOC_SIZED
|
||||||
|
|
194
client/src/thirdparty/stb_leakcheck.h
vendored
194
client/src/thirdparty/stb_leakcheck.h
vendored
|
@ -1,194 +0,0 @@
|
||||||
// stb_leakcheck.h - v0.6 - quick & dirty malloc leak-checking - public domain
|
|
||||||
// LICENSE
|
|
||||||
//
|
|
||||||
// See end of file.
|
|
||||||
|
|
||||||
#ifdef STB_LEAKCHECK_IMPLEMENTATION
|
|
||||||
#undef STB_LEAKCHECK_IMPLEMENTATION // don't implement more than once
|
|
||||||
|
|
||||||
// if we've already included leakcheck before, undefine the macros
|
|
||||||
#ifdef malloc
|
|
||||||
#undef malloc
|
|
||||||
#undef free
|
|
||||||
#undef realloc
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef STB_LEAKCHECK_OUTPUT_PIPE
|
|
||||||
#define STB_LEAKCHECK_OUTPUT_PIPE stdout
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
typedef struct malloc_info stb_leakcheck_malloc_info;
|
|
||||||
|
|
||||||
struct malloc_info
|
|
||||||
{
|
|
||||||
const char *file;
|
|
||||||
int line;
|
|
||||||
size_t size;
|
|
||||||
stb_leakcheck_malloc_info *next,*prev;
|
|
||||||
};
|
|
||||||
|
|
||||||
static stb_leakcheck_malloc_info *mi_head;
|
|
||||||
|
|
||||||
void *stb_leakcheck_malloc(size_t sz, const char *file, int line)
|
|
||||||
{
|
|
||||||
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) malloc(sz + sizeof(*mi));
|
|
||||||
if (mi == NULL) return mi;
|
|
||||||
mi->file = file;
|
|
||||||
mi->line = line;
|
|
||||||
mi->next = mi_head;
|
|
||||||
if (mi_head)
|
|
||||||
mi->next->prev = mi;
|
|
||||||
mi->prev = NULL;
|
|
||||||
mi->size = (int) sz;
|
|
||||||
mi_head = mi;
|
|
||||||
return mi+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stb_leakcheck_free(void *ptr)
|
|
||||||
{
|
|
||||||
if (ptr != NULL) {
|
|
||||||
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1;
|
|
||||||
mi->size = ~mi->size;
|
|
||||||
#ifndef STB_LEAKCHECK_SHOWALL
|
|
||||||
if (mi->prev == NULL) {
|
|
||||||
assert(mi_head == mi);
|
|
||||||
mi_head = mi->next;
|
|
||||||
} else
|
|
||||||
mi->prev->next = mi->next;
|
|
||||||
if (mi->next)
|
|
||||||
mi->next->prev = mi->prev;
|
|
||||||
free(mi);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line)
|
|
||||||
{
|
|
||||||
if (ptr == NULL) {
|
|
||||||
return stb_leakcheck_malloc(sz, file, line);
|
|
||||||
} else if (sz == 0) {
|
|
||||||
stb_leakcheck_free(ptr);
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1;
|
|
||||||
if (sz <= mi->size)
|
|
||||||
return ptr;
|
|
||||||
else {
|
|
||||||
#ifdef STB_LEAKCHECK_REALLOC_PRESERVE_MALLOC_FILELINE
|
|
||||||
void *q = stb_leakcheck_malloc(sz, mi->file, mi->line);
|
|
||||||
#else
|
|
||||||
void *q = stb_leakcheck_malloc(sz, file, line);
|
|
||||||
#endif
|
|
||||||
if (q) {
|
|
||||||
memcpy(q, ptr, mi->size);
|
|
||||||
stb_leakcheck_free(ptr);
|
|
||||||
}
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void stblkck_internal_print(const char *reason, stb_leakcheck_malloc_info *mi)
|
|
||||||
{
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900 // 1900=VS 2015
|
|
||||||
// Compilers that use the old MS C runtime library don't have %zd
|
|
||||||
// and the older ones don't even have %lld either... however, the old compilers
|
|
||||||
// without "long long" don't support 64-bit targets either, so here's the
|
|
||||||
// compromise:
|
|
||||||
#if _MSC_VER < 1400 // before VS 2005
|
|
||||||
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %8d bytes at %p\n", reason, mi->file, mi->line, (int)mi->size, (void*)(mi+1));
|
|
||||||
#else
|
|
||||||
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %16lld bytes at %p\n", reason, mi->file, mi->line, (long long)mi->size, (void*)(mi+1));
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
// Assume we have %zd on other targets.
|
|
||||||
#ifdef __MINGW32__
|
|
||||||
__mingw_fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1));
|
|
||||||
#else
|
|
||||||
fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1));
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void stb_leakcheck_dumpmem(void)
|
|
||||||
{
|
|
||||||
stb_leakcheck_malloc_info *mi = mi_head;
|
|
||||||
while (mi) {
|
|
||||||
if ((ptrdiff_t) mi->size >= 0)
|
|
||||||
stblkck_internal_print("LEAKED", mi);
|
|
||||||
mi = mi->next;
|
|
||||||
}
|
|
||||||
#ifdef STB_LEAKCHECK_SHOWALL
|
|
||||||
mi = mi_head;
|
|
||||||
while (mi) {
|
|
||||||
if ((ptrdiff_t) mi->size < 0)
|
|
||||||
stblkck_internal_print("FREED ", mi);
|
|
||||||
mi = mi->next;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif // STB_LEAKCHECK_IMPLEMENTATION
|
|
||||||
|
|
||||||
#if !defined(INCLUDE_STB_LEAKCHECK_H) || !defined(malloc)
|
|
||||||
#define INCLUDE_STB_LEAKCHECK_H
|
|
||||||
|
|
||||||
#include <stdlib.h> // we want to define the macros *after* stdlib to avoid a slew of errors
|
|
||||||
|
|
||||||
#define malloc(sz) stb_leakcheck_malloc(sz, __FILE__, __LINE__)
|
|
||||||
#define free(p) stb_leakcheck_free(p)
|
|
||||||
#define realloc(p,sz) stb_leakcheck_realloc(p,sz, __FILE__, __LINE__)
|
|
||||||
|
|
||||||
extern void * stb_leakcheck_malloc(size_t sz, const char *file, int line);
|
|
||||||
extern void * stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line);
|
|
||||||
extern void stb_leakcheck_free(void *ptr);
|
|
||||||
extern void stb_leakcheck_dumpmem(void);
|
|
||||||
|
|
||||||
#endif // INCLUDE_STB_LEAKCHECK_H
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
This software is available under 2 licenses -- choose whichever you prefer.
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
ALTERNATIVE A - MIT License
|
|
||||||
Copyright (c) 2017 Sean Barrett
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
of the Software, and to permit persons to whom the Software is furnished to do
|
|
||||||
so, subject to the following conditions:
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
|
||||||
This is free and unencumbered software released into the public domain.
|
|
||||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
|
||||||
software, either in source code form or as a compiled binary, for any purpose,
|
|
||||||
commercial or non-commercial, and by any means.
|
|
||||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
|
||||||
software dedicate any and all copyright interest in the software to the public
|
|
||||||
domain. We make this dedication for the benefit of the public at large and to
|
|
||||||
the detriment of our heirs and successors. We intend this dedication to be an
|
|
||||||
overt act of relinquishment in perpetuity of all present and future rights to
|
|
||||||
this software under copyright law.
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
*/
|
|
Loading…
Add table
Reference in a new issue