401 lines
10 KiB
C
401 lines
10 KiB
C
#include "E.h"
|
|
|
|
/*#define DBUG_MEM 1 */
|
|
|
|
/*#define MEM_OUT 1 */
|
|
|
|
#ifdef DBUG_MEM
|
|
#define POINTERS_SIZE 50000
|
|
static unsigned int num_pointers = 0;
|
|
static void *pointers_ptr[POINTERS_SIZE];
|
|
static unsigned int pointers_size[POINTERS_SIZE];
|
|
|
|
#ifdef MEM_OUT
|
|
static void *pointers_stack[POINTERS_SIZE][32];
|
|
static char pointers_file[POINTERS_SIZE][16];
|
|
static int pointers_line[POINTERS_SIZE];
|
|
static time_t pointers_time[POINTERS_SIZE];
|
|
|
|
#define PSTK(y, x) if (__builtin_frame_address(x)) \
|
|
pointers_stack[y][x] = __builtin_return_address(x);\
|
|
else goto end;
|
|
#define PST(y)\
|
|
{\
|
|
int _pi;\
|
|
for (_pi = 0; _pi < 32; _pi++)\
|
|
pointers_stack[y][_pi] = NULL;\
|
|
PSTK(y, 0); PSTK(y, 1); PSTK(y, 2); PSTK(y, 3); PSTK(y, 4);\
|
|
PSTK(y, 5); PSTK(y, 6); PSTK(y, 7); PSTK(y, 8); PSTK(y, 9);\
|
|
PSTK(y, 10); PSTK(y, 11); PSTK(y, 12); PSTK(y, 13); PSTK(y, 14);\
|
|
PSTK(y, 15); PSTK(y, 16); PSTK(y, 17); PSTK(y, 18); PSTK(y, 19);\
|
|
PSTK(y, 20); PSTK(y, 21); PSTK(y, 22); PSTK(y, 23); PSTK(y, 24);\
|
|
PSTK(y, 25); PSTK(y, 26); PSTK(y, 27); PSTK(y, 28); PSTK(y, 29);\
|
|
PSTK(y, 30); PSTK(y, 31);\
|
|
end: \
|
|
}
|
|
|
|
static struct _symtab
|
|
{
|
|
void *val;
|
|
char *symbol;
|
|
}
|
|
*sym = NULL;
|
|
|
|
static int sym_count = 0;
|
|
|
|
char *
|
|
getsym(void *p)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sym_count - 1; i++)
|
|
{
|
|
if ((p > sym[i].val) && (p < sym[i + 1].val))
|
|
return sym[i].symbol;
|
|
}
|
|
return "";
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
void
|
|
EDisplayMemUse()
|
|
{
|
|
#ifdef DBUG_MEM
|
|
FILE *f;
|
|
unsigned int i, min, max, sum;
|
|
|
|
max = 0;
|
|
min = 0x7ffffff;
|
|
sum = 0;
|
|
if (!sym)
|
|
{
|
|
f = fopen("e.sym", "r");
|
|
if (f)
|
|
{
|
|
void *p;
|
|
char buf[256];
|
|
|
|
while (fscanf(f, "%x %*s %250s\n", &p, buf) != EOF)
|
|
{
|
|
sym_count++;
|
|
sym = realloc(sym, sizeof(struct _symtab) * sym_count);
|
|
|
|
sym[sym_count - 1].val = p;
|
|
sym[sym_count - 1].symbol = strdup(buf);
|
|
}
|
|
fclose(f);
|
|
}
|
|
}
|
|
f = fopen("e.mem.out", "w");
|
|
for (i = 0; i < num_pointers; i++)
|
|
{
|
|
char tm[32];
|
|
struct tm tim;
|
|
struct tm *tim2;
|
|
time_t t2;
|
|
|
|
sum += pointers_size[i];
|
|
if (pointers_size[i] < min)
|
|
min = pointers_size[i];
|
|
if (pointers_size[i] > max)
|
|
max = pointers_size[i];
|
|
t2 = pointers_time[i];
|
|
tim2 = localtime(&t2);
|
|
if (tim2)
|
|
{
|
|
memcpy(&tim, tim2, sizeof(struct tm));
|
|
|
|
strftime(tm, 31, "%T", &tim);
|
|
}
|
|
fprintf(f, "%6i > %p %5i @ %s - %16s line %5i : "
|
|
"%s %s %s %s %s %s %s %s "
|
|
"%s %s %s %s %s %s %s %s "
|
|
"%s %s %s %s %s %s %s %s "
|
|
"%s %s %s %s %s %s %s %s\n",
|
|
i, pointers_ptr[i], pointers_size[i], tm,
|
|
pointers_file[i], pointers_line[i],
|
|
getsym(pointers_stack[i][0]), getsym(pointers_stack[i][1]),
|
|
getsym(pointers_stack[i][2]), getsym(pointers_stack[i][3]),
|
|
getsym(pointers_stack[i][4]), getsym(pointers_stack[i][5]),
|
|
getsym(pointers_stack[i][6]), getsym(pointers_stack[i][7]),
|
|
getsym(pointers_stack[i][8]), getsym(pointers_stack[i][9]),
|
|
getsym(pointers_stack[i][10]), getsym(pointers_stack[i][11]),
|
|
getsym(pointers_stack[i][12]), getsym(pointers_stack[i][13]),
|
|
getsym(pointers_stack[i][14]), getsym(pointers_stack[i][15]),
|
|
getsym(pointers_stack[i][16]), getsym(pointers_stack[i][17]),
|
|
getsym(pointers_stack[i][18]), getsym(pointers_stack[i][19]),
|
|
getsym(pointers_stack[i][20]), getsym(pointers_stack[i][21]),
|
|
getsym(pointers_stack[i][22]), getsym(pointers_stack[i][23]),
|
|
getsym(pointers_stack[i][24]), getsym(pointers_stack[i][25]),
|
|
getsym(pointers_stack[i][26]), getsym(pointers_stack[i][27]),
|
|
getsym(pointers_stack[i][28]), getsym(pointers_stack[i][29]),
|
|
getsym(pointers_stack[i][30]), getsym(pointers_stack[i][31]));
|
|
}
|
|
if (num_pointers > 0)
|
|
{
|
|
fprintf(f, "Num:%6i Sum:%8i Av:%8i Min:%8i Max%6i\n",
|
|
num_pointers, sum, sum / num_pointers, min, max);
|
|
}
|
|
fclose(f);
|
|
#endif
|
|
}
|
|
|
|
#if defined(__FILE__) && defined(__LINE__)
|
|
void *
|
|
__Emalloc(int size, const char *file, int line)
|
|
{
|
|
void *p;
|
|
|
|
EDBUG(9, "Emalloc");
|
|
if (size <= 0)
|
|
return NULL;
|
|
p = malloc(size);
|
|
if (!p)
|
|
{
|
|
if (disp)
|
|
UngrabX();
|
|
ASSIGN_ALERT("Cannot allocate enough memory",
|
|
"Ignore this",
|
|
"Restart Enlightenment",
|
|
"Quit Enlightenment");
|
|
Alert("WARNING!!!!!!\n"
|
|
"\n"
|
|
"Allocation for %i bytes (%3.0f Kb or %3.1f Mb) did not succeed.\n"
|
|
"\n"
|
|
"Either this is a bug where rediculous amounts of memory\n"
|
|
"are being allocated, or your system has run out of both\n"
|
|
"real and virtual memory and is unable to satisfy the request.\n"
|
|
"\n"
|
|
"If you have a low memory system it is suggested to either\n"
|
|
"purchase more memory, increase SWAP space, or reconfigure\n"
|
|
"Enlightenment to use less resources by turning features off.\n"
|
|
"\n"
|
|
"The malloc requested was at %s, line %d\n ",
|
|
size, (float)size / 1024, (float)size / (1024 * 1024), file, line);
|
|
RESET_ALERT;
|
|
}
|
|
#ifdef DBUG_MEM
|
|
if (p)
|
|
{
|
|
num_pointers++;
|
|
pointers_ptr[num_pointers - 1] = p;
|
|
pointers_size[num_pointers - 1] = size;
|
|
#ifdef MEM_OUT
|
|
strcpy(pointers_file[num_pointers - 1], file);
|
|
pointers_line[num_pointers - 1] = line;
|
|
pointers_time[num_pointers - 1] = time(NULL);
|
|
PST(num_pointers - 1);
|
|
#endif
|
|
}
|
|
#endif
|
|
EDBUG_RETURN(p);
|
|
}
|
|
|
|
void *
|
|
__Erealloc(void *ptr, int size, const char *file, int line)
|
|
{
|
|
void *p;
|
|
|
|
#ifdef DBUG_MEM
|
|
char bad = 0;
|
|
|
|
#endif
|
|
|
|
if (ptr == NULL)
|
|
{
|
|
if (size > 0)
|
|
return __Emalloc(size, file, line);
|
|
else
|
|
return NULL;
|
|
}
|
|
/* If we get here, we know ptr != NULL, so don't test for that case -- mej */
|
|
if (size <= 0)
|
|
{
|
|
__Efree(ptr, file, line);
|
|
return NULL;
|
|
}
|
|
EDBUG(9, "Erealloc");
|
|
#ifdef DBUG_MEM
|
|
if (ptr)
|
|
{
|
|
unsigned int i;
|
|
|
|
bad = 1;
|
|
for (i = 0; i < num_pointers; i++)
|
|
{
|
|
if (pointers_ptr[i] == ptr)
|
|
{
|
|
bad = 0;
|
|
i = num_pointers;
|
|
}
|
|
}
|
|
}
|
|
if (bad)
|
|
{
|
|
if (disp)
|
|
UngrabX();
|
|
ASSIGN_ALERT("Error in reallocating memory that hasn't been allocated",
|
|
"Ignore this",
|
|
"Restart Enlightenment",
|
|
"Quit Enlightenment");
|
|
Alert("WARNING!!!!!!\n"
|
|
"\n"
|
|
"Re-allocation for %i bytes (%3.0f Kb or %f3.1 Mb)\n"
|
|
"for pointer %x is attempting to re-allocate memory for a\n"
|
|
"memory chunk that has not been allocated or has already been\n"
|
|
"freed.\n"
|
|
"\n"
|
|
"This is definitely a bug. Please report it.\n"
|
|
"\n"
|
|
"The error occured at %s, line %d.\n",
|
|
size, (float)size / 1024, (float)size / (1024 * 1024), ptr, file, line);
|
|
RESET_ALERT;
|
|
EDBUG_RETURN(NULL);
|
|
}
|
|
#endif
|
|
p = realloc(ptr, size);
|
|
if ((!p) && (size != 0))
|
|
{
|
|
if (disp)
|
|
UngrabX();
|
|
ASSIGN_ALERT("Cannot allocate enough memory",
|
|
"Ignore this",
|
|
"Restart Enlightenment",
|
|
"Quit Enlightenment");
|
|
Alert("WARNING!!!!!!\n"
|
|
"\n"
|
|
"Re-allocation for %i bytes (%3.0f Kb or %3.1f Mb) did not succeed.\n"
|
|
"\n"
|
|
"Either this is a bug where rediculous amounts of memory\n"
|
|
"are being allocated, or your system has run out of both\n"
|
|
"real and virtual memory and is unable to satisfy the request.\n"
|
|
"\n"
|
|
"If you have a low memory system it is suggested to either\n"
|
|
"purchase more memory, increase SWAP space, or reconfigure\n"
|
|
"Enlightenment to use less resources by turning features off.\n"
|
|
"\n"
|
|
"The realloc requested was at %s, line %d\n ",
|
|
size, (float)size / 1024, (float)size / (1024 * 1024), file, line);
|
|
RESET_ALERT;
|
|
}
|
|
#ifdef DBUG_MEM
|
|
if (p)
|
|
{
|
|
unsigned int i;
|
|
|
|
bad = 1;
|
|
for (i = 0; i < num_pointers; i++)
|
|
{
|
|
if (pointers_ptr[i] == ptr)
|
|
{
|
|
pointers_size[i] = size;
|
|
pointers_ptr[i] = p;
|
|
i = num_pointers;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
EDBUG_RETURN(p);
|
|
}
|
|
|
|
void
|
|
__Efree(void *ptr, const char *file, int line)
|
|
{
|
|
#ifdef DBUG_MEM
|
|
char bad = 0;
|
|
|
|
#endif
|
|
EDBUG(9, "Efree");
|
|
#ifdef DBUG_MEM
|
|
{
|
|
unsigned int i, j, k;
|
|
|
|
bad = 1;
|
|
for (i = 0; i < num_pointers; i++)
|
|
{
|
|
if (pointers_ptr[i] == ptr)
|
|
{
|
|
for (j = i; j < num_pointers - 1; j++)
|
|
{
|
|
pointers_ptr[j] = pointers_ptr[j + 1];
|
|
pointers_size[j] = pointers_size[j + 1];
|
|
#ifdef MEM_OUT
|
|
for (k = 0; k < 32; k++)
|
|
pointers_stack[j][k] = pointers_stack[j + 1][k];
|
|
strcpy(pointers_file[j], pointers_file[j + 1]);
|
|
pointers_line[j] = pointers_line[j + 1];
|
|
pointers_time[j] = pointers_time[j + 1];
|
|
#endif
|
|
}
|
|
bad = 0;
|
|
i = num_pointers;
|
|
num_pointers--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (bad)
|
|
{
|
|
if (disp)
|
|
UngrabX();
|
|
ASSIGN_ALERT("Error in freeing memory that hasn't been allocated",
|
|
"Ignore this",
|
|
"Restart Enlightenment",
|
|
"Quit Enlightenment");
|
|
Alert("WARNING!!!!!!\n"
|
|
"\n"
|
|
"freeing for pointer %x is attempting to free memory for a\n"
|
|
"memory chunk that has not been allocated, or has already been\n"
|
|
"freed.\n"
|
|
"\n"
|
|
"This is definitely a bug. Please report it.\n"
|
|
"\n"
|
|
"The error occured at %s, line %d.\n",
|
|
ptr, file, line);
|
|
RESET_ALERT;
|
|
EDBUG_RETURN_;
|
|
}
|
|
#endif
|
|
if (!ptr)
|
|
{
|
|
if (disp)
|
|
UngrabX();
|
|
ASSIGN_ALERT("Error in attempting to free NULL pointer",
|
|
"Ignore this (safe)",
|
|
"Restart Enlightenment",
|
|
"Quit Enlightenment");
|
|
Alert("WARNING!!!!!!\n"
|
|
"\n"
|
|
"Enlightenment attempted to free a NULL pointer.\n"
|
|
"\n"
|
|
"This is definitely a bug. Please report it.\n"
|
|
"It is safe to ignore this error and continue running Enlightenment.\n"
|
|
"\n"
|
|
"The pointert value was %x.\n"
|
|
"The error occured at %s, line %d.\n",
|
|
ptr, file, line);
|
|
RESET_ALERT;
|
|
EDBUG_RETURN_;
|
|
}
|
|
free(ptr);
|
|
EDBUG_RETURN_;
|
|
}
|
|
#endif
|
|
|
|
char *
|
|
duplicate(char *s)
|
|
{
|
|
char *ss;
|
|
int sz;
|
|
|
|
EDBUG(9, "duplicate");
|
|
if (!s)
|
|
EDBUG_RETURN(NULL);
|
|
sz = strlen(s);
|
|
ss = Emalloc(sz + 1);
|
|
strncpy(ss, s, sz + 1);
|
|
EDBUG_RETURN(ss);
|
|
}
|