jcs
/subtext
/amendments
/331
util: Make x* allocation functions no longer fatal on failure
Display a warning, but return NULL
Also remove MALLOC_DEBUG, it is not as helpful as I wanted and just
bloats things having to store all these note strings
jcs made amendment 331 about 1 year ago
--- util.c Sun Feb 5 11:13:11 2023
+++ util.c Wed Mar 1 15:45:47 2023
@@ -83,28 +83,6 @@ enum {
APPICON_ALERT
};
-/*
- * Define to audit each malloc and free and verify that a pointer isn't
- * double-freed. The list of outstanding allocations can be checked by
- * looking through malloc_map.
- */
-//#define MALLOC_DEBUG
-
-#ifdef MALLOC_DEBUG
-/*
- * List of allocations, updated at xmalloc() and xfree(). If an address
- * passed to xfree() isn't in the list, it indicates a double-free.
- */
-#define MALLOC_MAP_CHUNK_SIZE 1024
-struct malloc_map_e {
- unsigned long addr;
- unsigned long size;
- char note[MALLOC_NOTE_SIZE];
-} *malloc_map = NULL;
-unsigned long malloc_map_size = 0;
-static bool malloc_map_compact = false;
-#endif
-
void vwarn(short alert_func, const char *format, va_list ap);
/*
@@ -116,18 +94,11 @@ void
util_init(void)
{
alert_ditl_h = xNewHandle(sizeof(alert_ditl));
+ if (alert_ditl_h == NULL)
+ ExitToShell();
HLock(alert_ditl_h);
memcpy(*alert_ditl_h, alert_ditl, sizeof(alert_ditl));
HUnlock(alert_ditl_h);
-
-#ifdef MALLOC_DEBUG
- malloc_map_size = MALLOC_MAP_CHUNK_SIZE;
- malloc_map = (struct malloc_map_e *)NewPtr(malloc_map_size *
- sizeof(struct malloc_map_e));
- if (malloc_map == NULL)
- panic("NewPtr(%lu) failed", MALLOC_MAP_CHUNK_SIZE);
- memset(malloc_map, 0, malloc_map_size);
-#endif
}
/*
@@ -137,65 +108,17 @@ util_init(void)
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
-xmalloc(size_t size, char *note)
+xmalloc(size_t size)
{
void *ptr;
-#ifdef MALLOC_DEBUG
- struct malloc_map_e *new_malloc_map;
- unsigned short n, j;
-#endif
if (size == 0)
panic("xmalloc: zero size");
ptr = NewPtr(size);
if (ptr == NULL)
- panic("xmalloc(%lu) failed", size);
+ warn("Insufficient memory available: xmalloc(%lu) failed", size);
-#ifdef MALLOC_DEBUG
- if (malloc_map_compact) {
- for (n = 0; n < malloc_map_size; n++) {
- if (malloc_map[n].addr != 0)
- continue;
-
- for (j = n + 1; j < malloc_map_size; j++) {
- if (malloc_map[j].addr == 0)
- continue;
-
- malloc_map[n] = malloc_map[j];
- memset(&malloc_map[j], 0, sizeof(struct malloc_map_e));
- break;
- }
- }
-
- malloc_map_compact = false;
- }
-
- for (n = 0; n <= malloc_map_size; n++) {
- if (n == malloc_map_size) {
- malloc_map_size += MALLOC_MAP_CHUNK_SIZE;
- warn("xmalloc(%lu): out of malloc map entries, maybe a "
- "memory leak, resizing to %ld", size, malloc_map_size);
- new_malloc_map = (struct malloc_map_e *)NewPtr(
- malloc_map_size * sizeof(struct malloc_map_e));
- if (new_malloc_map == NULL)
- panic("out of memory resizing malloc map");
- memcpy(new_malloc_map, malloc_map,
- (malloc_map_size - MALLOC_MAP_CHUNK_SIZE) *
- sizeof(struct malloc_map_e));
- DisposePtr(malloc_map);
- malloc_map = new_malloc_map;
- }
- if (malloc_map[n].addr == 0) {
- malloc_map[n].addr = (unsigned long)ptr;
- malloc_map[n].size = size;
- strlcpy(malloc_map[n].note, note, sizeof(malloc_map[n].note));
- break;
- }
- n = n;
- }
-#endif
-
return ptr;
}
@@ -204,89 +127,51 @@ xfree(void *ptrptr)
{
unsigned long *addr = (unsigned long *)ptrptr;
void *ptr;
-#ifdef MALLOC_DEBUG
- unsigned long n;
-#endif
if (ptrptr == NULL)
panic("xfree(NULL)");
ptr = (void *)*addr;
- if (ptr == NULL)
- panic("xfree(&NULL) likely a double-free");
-
-#ifdef MALLOC_DEBUG
- for (n = 0; n <= malloc_map_size; n++) {
- if (n == malloc_map_size)
- panic("xfree(0x%lx): can't find in alloc map, likely "
- "double free()", *addr);
- if (malloc_map[n].addr == *addr) {
- malloc_map[n].addr = 0;
- malloc_map[n].size = 0;
- malloc_map[n].note[0] = '\0';
- break;
- }
+ if (ptr == NULL) {
+ warn("xfree(&NULL) likely a double-free");
+ return;
}
-#endif
-
+
DisposePtr(ptr);
-
*addr = 0L;
}
void *
-xmalloczero(size_t size, char *note)
+xmalloczero(size_t size)
{
void *ptr;
- ptr = xmalloc(size, note);
- memset(ptr, 0, size);
+ ptr = xmalloc(size);
+ if (ptr != NULL)
+ memset(ptr, 0, size);
return ptr;
}
void *
-xcalloc(size_t nmemb, size_t size, char *note)
+xcalloc(size_t nmemb, size_t size)
{
void *ptr;
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size)
panic("xcalloc(%lu, %lu) overflow", nmemb, size);
- ptr = xmalloczero(nmemb * size, note);
- if (ptr == NULL)
- panic("xcalloc(%lu, %lu) failed", nmemb, size);
-
- return ptr;
+
+ return xmalloczero(nmemb * size);
}
void *
xrealloc(void *src, size_t size)
{
void *ptr, *tsrc;
-#ifdef MALLOC_DEBUG
- unsigned long n;
-#endif
- char note[MALLOC_NOTE_SIZE] = "realloc from null";
-#ifdef MALLOC_DEBUG
- if (src != NULL) {
- for (n = 0; n <= malloc_map_size; n++) {
- if (n == malloc_map_size) {
- panic("xrealloc(%lu): can't find in alloc map, likely "
- "double free()", (unsigned long)src);
- return NULL;
- }
- if (malloc_map[n].addr == (unsigned long)src) {
- strlcpy(note, malloc_map[n].note, sizeof(note));
- break;
- }
- }
- }
-#endif
-
- ptr = xmalloc(size, note);
- if (src != NULL) {
+ ptr = xmalloc(size);
+ if (ptr != NULL && src != NULL) {
memcpy(ptr, src, size);
tsrc = src;
xfree(&tsrc);
@@ -301,25 +186,26 @@ xreallocarray(void *optr, size_t nmemb, size_t size)
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size)
panic("xreallocarray(%lu, %lu) failed", nmemb, size);
+
return xrealloc(optr, size * nmemb);
}
char *
-xstrdup(const char *str, char *note)
+xstrdup(const char *str)
{
char *cp;
size_t len;
len = strlen(str);
+ cp = xmalloc(len + 1);
+ if (cp != NULL)
+ strlcpy(cp, str, len + 1);
- cp = xmalloc(len + 1, note);
- strlcpy(cp, str, len + 1);
-
return cp;
}
char *
-xstrndup(const char *str, size_t maxlen, char *note)
+xstrndup(const char *str, size_t maxlen)
{
char *copy;
const char *cp;
@@ -330,14 +216,15 @@ xstrndup(const char *str, size_t maxlen, char *note)
;
len = (size_t)(cp - str);
- copy = xmalloc(len + 1, note);
- (void)memcpy(copy, str, len);
- copy[len] = '\0';
+ copy = xmalloc(len + 1);
+ if (copy != NULL) {
+ (void)memcpy(copy, str, len);
+ copy[len] = '\0';
+ }
return copy;
}
-
/*
* String functions
*/
@@ -349,8 +236,11 @@ getline(char *str, size_t len, char **ret)
for (i = 0; i < len; i++) {
if (str[i] == '\r' || i == len - 1) {
- if (*ret == NULL)
- *ret = xmalloc(i + 1, "getline");
+ if (*ret == NULL) {
+ *ret = xmalloc(i + 1);
+ if (*ret == NULL)
+ return -1;
+ }
memcpy(*ret, str, i + 1);
(*ret)[i] = '\0';
return i + 1;
@@ -713,7 +603,7 @@ center_in_screen(short width, short height, bool title
}
Point
-centered_sf_dialog(void)
+centered_sfget_dialog(void)
{
Point p;
Rect r;
@@ -725,6 +615,18 @@ centered_sf_dialog(void)
return p;
}
+Point
+centered_sfput_dialog(void)
+{
+ Point p;
+ Rect r;
+
+ center_in_screen(320, 200, false, &r);
+ p.h = r.left;
+ p.v = r.top;
+
+ return p;
+}
/*
* General Mac-specific non-GUI functions
@@ -797,32 +699,38 @@ xGetStringAsChar(short id)
h = xGetString(id);
HLock(h);
l = (*h)[0];
- out = xmalloc(l + 1, "xGetStringAsChar");
- memcpy((void *)out, (void *)(*h + 1), l);
- out[l] = '\0';
+ out = xmalloc(l + 1);
+ if (out != NULL) {
+ memcpy((void *)out, (void *)(*h + 1), l);
+ out[l] = '\0';
+ }
ReleaseResource(h);
return out;
}
-long
-xGetStringAsLong(short id)
+bool
+xGetStringAsLong(short id, long *ret)
{
char *c;
- long r;
c = xGetStringAsChar(id);
- r = atol(c);
+ if (c == NULL)
+ return false;
+ *ret = atol(c);
xfree(&c);
- return r;
+ return true;
}
-void
+bool
xSetHandleSize(Handle h, Size s)
{
SetHandleSize(h, s);
- if (MemError())
- panic("Failed to SetHandleSize to %ld", s);
+ if (MemError()) {
+ warn("Failed to SetHandleSize to %ld", s);
+ return false;
+ }
+ return true;
}
/*
@@ -840,6 +748,8 @@ getpath(short vRefNum, Str255 fileName, Str255 *ret, b
char *tmpret = NULL, *tmp = NULL;
char *lastcolon;
+ *ret[0] = 0;
+
if (strchr((char *)fileName + 1, ':') != NULL) {
/* already a full path */
memcpy(*ret, fileName, 256);
@@ -852,8 +762,10 @@ getpath(short vRefNum, Str255 fileName, Str255 *ret, b
return 0;
}
- name = xmalloc(FILENAME_MAX, "getpath");
-
+ name = xmalloc(FILENAME_MAX);
+ if (name == NULL)
+ return 1;
+
wdir.ioVRefNum = wdir.ioWDVRefNum = vRefNum;
wdir.ioWDIndex = 0;
wdir.ioWDProcID = 0;
@@ -886,9 +798,18 @@ getpath(short vRefNum, Str255 fileName, Str255 *ret, b
wcinfo.ioDrParID = wdir.ioWDDirID;
wcinfo.ioDrDirID = wdir.ioWDDirID;
- tmp = xmalloc(FILENAME_MAX, "getpath");
- tmpret = xmalloc(FILENAME_MAX, "getpath");
-
+ tmp = xmalloc(FILENAME_MAX);
+ if (tmp == NULL) {
+ xfree(&name);
+ return 1;
+ }
+ tmpret = xmalloc(FILENAME_MAX);
+ if (tmp == NULL) {
+ xfree(&tmp);
+ xfree(&name);
+ return 1;
+ }
+
/* go backwards, prepending each folder's parent */
while (wcinfo.ioDrParID != 1) {
wcinfo.ioDrDirID = wcinfo.ioDrParID; /* .. */
@@ -940,7 +861,9 @@ stat(char *path, struct stat *sb)
char *ppath;
short ret;
- ppath = xstrdup(path, "stat");
+ ppath = xstrdup(path);
+ if (ppath == NULL)
+ return -1;
CtoPstr(ppath);
ret = FStat((unsigned char *)ppath, sb);
xfree(&ppath);
@@ -1082,7 +1005,9 @@ copy_file_contents(short source_ref, short dest_ref)
if (error)
return error;
- buf = xmalloc(1024, "copy_file_contents");
+ buf = xmalloc(1024);
+ if (buf == NULL)
+ return -1;
while (source_size > 0) {
count = 1024;
@@ -1245,6 +1170,10 @@ DrawGrowIconOnly(WindowPtr win)
RgnHandle tmp;
GetClip(tmp = NewRgn());
+ if (tmp == NULL) {
+ warn("NewRgn() failed");
+ return;
+ }
r = win->portRect;
r.top = r.bottom - SCROLLBAR_WIDTH;
r.left = r.right - SCROLLBAR_WIDTH + 1;
--- util.h Sun Feb 5 11:13:11 2023
+++ util.h Wed Mar 1 15:37:54 2023
@@ -94,15 +94,15 @@ struct stat {
void util_init(void);
-void * xmalloc(size_t, char *note);
+void * xmalloc(size_t);
void xfree(void *ptrptr);
void xfree_verify(void);
-void * xmalloczero(size_t, char *note);
-void * xcalloc(size_t, size_t, char *note);
+void * xmalloczero(size_t);
+void * xcalloc(size_t, size_t);
void * xrealloc(void *src, size_t size);
void * xreallocarray(void *, size_t, size_t);
-char * xstrdup(const char *, char *note);
-char * xstrndup(const char *str, size_t maxlen, char *note);
+char * xstrdup(const char *);
+char * xstrndup(const char *str, size_t maxlen);
short getline(char *str, size_t len, char **ret);
const char * ordinal(unsigned short n);
@@ -125,14 +125,15 @@ void about(char *program_name);
void progress(char *format, ...);
void window_rect(WindowPtr win, Rect *ret);
void center_in_screen(short width, short height, bool titlebar, Rect *b);
-Point centered_sf_dialog(void);
+Point centered_sfget_dialog(void);
+Point centered_sfput_dialog(void);
Handle xNewHandle(size_t size);
Handle xGetResource(ResType type, short id);
StringHandle xGetString(short id);
char * xGetStringAsChar(short id);
-long xGetStringAsLong(short id);
-void xSetHandleSize(Handle h, Size s);
+bool xGetStringAsLong(short id, long *ret);
+bool xSetHandleSize(Handle h, Size s);
short getpath(short vRefNum, Str255 fileName, Str255 *ret, bool include_file);
bool FIsDir(Str255 path);
@@ -169,7 +170,5 @@ char * strndup(const char *str, size_t maxlen);
char * strsep(char **stringp, const char *delim);
int snprintf(char *s, size_t size, const char *fmt, ...);
int vsnprintf(char *s, size_t size, const char *fmt, void *p);
-
-void malloc_map_dump(void);
#endif