#define _LARGEFILE64_SOURCE /* required for GLIBC to enable stat64 and friends */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdarg.h>
#include <regex.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "mt.h"
#include "error.h"
#include "globals.h"
#include "term.h"
#include "utils.h"
#include "mem.h"
#ifndef _DEBUG
#define MEMLOG(x)
void dump_mem(int sig)
{
}
#else
void MEMLOG(char *s, ...)
{
va_list ap;
FILE *fh = fopen("log.log", "a+");
if (!fh)
error_exit(__FILE__, __PRETTY_FUNCTION__, __LINE__, "error logging\n");
va_start(ap, s);
vfprintf(fh, s, ap);
va_end(ap);
fclose(fh);
}
typedef struct
{
void *p;
int size;
char *file;
char *function;
int line;
} memlist;
memlist *pm = NULL;
int n_pm = 0;
void dump_mem(int sig)
{
int loop;
signal(SIGHUP, dump_mem);
if (sig != SIGHUP)
error_exit(__FILE__, __PRETTY_FUNCTION__, __LINE__, "Unexpected signal %d.\n", sig);
MEMLOG("%d elements of memory used\n", n_pm);
for(loop=0; loop<n_pm; loop++)
{
MEMLOG("%06d] %p %d (%s:%s@%d)\n", loop, pm[loop].p, pm[loop].size, pm[loop].file, pm[loop].function, pm[loop].line);
}
MEMLOG("--- finished memory dump\n");
}
int remove_mem_element(void *p)
{
int old_size = 0;
if (p)
{
int loop;
for(loop=0; loop<n_pm; loop++)
{
if (pm[loop].p == p)
{
int n_to_move;
old_size = pm[loop].size;
n_to_move = (n_pm - loop) - 1;
if (n_to_move > 0)
memmove(&pm[loop], &pm[loop + 1], n_to_move * sizeof(memlist));
else if (n_to_move < 0)
error_exit(__FILE__, __PRETTY_FUNCTION__, __LINE__, "n_to_move < 0!\n");
n_pm--;
loop=-1;
break;
}
}
if (loop != -1)
{
MEMLOG("remove_mem_element: pointer %p not found\n", p);
}
if (n_pm)
{
pm = (memlist *)realloc(pm, sizeof(memlist) * n_pm);
if (!pm) error_exit(__FILE__, __PRETTY_FUNCTION__, __LINE__, "Failed to shrink memory list to %d elements.\n", n_pm);
}
else
{
free(pm);
pm = NULL;
}
}
return old_size;
}
void add_mem_element(void *p, int size, char *file, const char *function, int line)
{
pm = (memlist *)realloc(pm, sizeof(memlist) * (n_pm + 1));
if (!pm) error_exit(__FILE__, __PRETTY_FUNCTION__, __LINE__, "Failed to grow memory list from %d elements.\n", n_pm);
pm[n_pm].p = p;
pm[n_pm].size = size;
pm[n_pm].file = file;
pm[n_pm].function = (char *)function;
pm[n_pm].line = line;
n_pm++;
}
#endif
void myfree(void *p)
{
#ifdef _DEBUG
(void)remove_mem_element(p);
#endif
free(p);
}
void * myrealloc(void *oldp, int new_size, char *file, const char *function, int line)
{
#ifdef _DEBUG
int old_size;
void *newp;
if (new_size <= 0)
error_exit(file, function, line, "Tried to allocate %d bytes which is wrong.\n", new_size);
newp = realloc(oldp, new_size);
if (!newp)
error_exit(file, function, line, "Failed to reallocate a memory block to %d bytes.\n", new_size);
old_size = remove_mem_element(oldp);
add_mem_element(newp, new_size, file, function, line);
signal(SIGHUP, dump_mem);
if (new_size > old_size)
memset(&((char *)newp)[old_size], 0xf1, new_size - old_size);
/* rand_size = new_size - old_size;
if (rand_size > 0)
{
MEMLOG("randomizing(%s) %d bytes\n", what, rand_size);
memset(&((char *)newp)[old_size], rand_val, rand_size);
}
*/
#else
/* ----------------------------------------------------
* add code for repeatingly retry? -> then configurable
* via configurationfile with number of retries and/or
* sleep
* ----------------------------------------------------
*/
void *newp = realloc(oldp, new_size);
if (!newp)
error_exit(file, function, line, "Failed to reallocate a memory block to %d bytes.\n", new_size);
#endif
return newp;
}
void * mymalloc(int size, char *file, const char *function, int line)
{
return myrealloc(NULL, size, file, function, line);
}
char * mystrdup(char *in, char *file, const char *function, int line)
{
#ifdef _DEBUG
int len = strlen(in) + 1;
char *newp = (char *)mymalloc(len, file, function, line);
memcpy(newp, in, len);
return newp;
#else
char *newp = strdup(in);
if (!newp)
error_exit(file, function, line, "Failed to duplicate a string: out of memory?\n");
return newp;
#endif
}
#ifdef _DEBUG
void clean_memory(void)
{
int loop;
/* color schemes */
for(loop=0; loop<n_cschemes; loop++)
{
int loop2;
myfree(cschemes[loop].name);
myfree(cschemes[loop].descr);
for(loop2=0; loop2<cschemes[loop].n; loop2++)
{
regfree(&cschemes[loop].pentries[loop2].regex);
}
myfree(cschemes[loop].color_script.script);
myfree(cschemes[loop].pentries);
}
myfree(cschemes);
/* colors */
myfree(cp.fg_color);
myfree(cp.bg_color);
/* text buffers */
for(loop=0; loop<nfd; loop++)
delete_be_in_buffer(&lb[loop]);
myfree(lb);
/* programs array */
for(loop=0; loop<nfd; loop++)
{
proginfo *cur = &pi[loop];
while(cur)
{
proginfo *pcur = cur;
int loop2;
for(loop2=0; loop2<cur -> n_strip; loop2++)
{
if ((cur -> pstrip)[loop2].type == STRIP_TYPE_REGEXP ||
(cur -> pstrip)[loop2].type == STRIP_KEEP_SUBSTR)
{
regfree(&(cur -> pstrip)[loop2].regex);
myfree ((cur -> pstrip)[loop2].regex_str);
}
myfree ((cur -> pstrip)[loop2].del);
}
myfree(cur -> pstrip);
myfree(cur -> filename);
for(loop2=0; loop2<cur -> n_redirect; loop2++)
myfree((cur -> predir)[loop2].redirect);
myfree(cur -> predir);
myfree(cur -> label);
free_iat(&cur -> conversions);
myfree(cur -> incomplete_line);
myfree(cur -> win_title);
delete_array(cur -> restart.diff.bcur, cur -> restart.diff.ncur);
delete_array(cur -> restart.diff.bprev, cur -> restart.diff.nprev);
myfree(cur -> repeat.last_line);
free_iat(&cur -> cdef.color_schemes);
delete_popup(cur -> status);
delete_popup(cur -> data);
for(loop2=0; loop2<cur -> n_re; loop2++)
free_re(&(cur -> pre)[loop2]);
myfree(cur -> pre);
cur = cur -> next;
if (pcur != &pi[loop])
myfree(pcur);
}
}
myfree(pi);
/* parameters per file */
for(loop=0; loop<n_pars_per_file; loop++)
{
int loop2;
for(loop2=0; loop2<ppf[loop].n_colorschemes; loop2++)
myfree(ppf[loop].colorschemes[loop2]);
myfree(ppf[loop].colorschemes);
if (ppf[loop].re_str)
{
regfree(&ppf[loop].regex);
myfree(ppf[loop].re_str);
}
free_iat(&ppf[loop].filterschemes);
free_iat(&ppf[loop].editschemes);
for(loop2=0; loop2<ppf[loop].n_conversion_schemes; loop2++)
myfree(ppf[loop].conversion_schemes[loop2]);
myfree(ppf[loop].conversion_schemes);
}
myfree(ppf);
/* conversions */
for(loop=0; loop<n_conversions; loop++)
{
int loop2;
myfree(conversions[loop].name);
for(loop2=0; loop2<conversions[loop].n; loop2++)
regfree(&conversions[loop].pcb[loop2].regex);
myfree(conversions[loop].pcb);
myfree(conversions[loop].pcs -> script);
myfree(conversions[loop].pcs);
}
myfree(conversions);
/* filterschemes */
for(loop=0; loop<n_fs; loop++)
{
int loop2;
myfree(pfs[loop].fs_name);
myfree(pfs[loop].fs_desc);
for(loop2=0; loop2<pfs[loop].n_re; loop2++)
free_re(&pfs[loop].pre[loop2]);
myfree(pfs[loop].pre);
}
myfree(pfs);
/* edit schemes */
for(loop=0; loop<n_es; loop++)
{
int loop2;
myfree(pes[loop].es_name);
myfree(pes[loop].es_desc);
for(loop2=0; loop2<pes[loop].n_strips; loop2++)
{
regfree(&pes[loop].strips[loop2].regex);
myfree(pes[loop].strips[loop2].regex_str);
myfree(pes[loop].strips[loop2].del);
}
myfree(pes[loop].strips);
}
myfree(pes);
/* keybindings */
for(loop=0; loop<n_keybindings; loop++)
myfree(keybindings[loop].command);
myfree(keybindings);
/* splitlines */
for(loop=0; loop<n_splitlines; loop++)
delete_popup(splitlines[loop]);
myfree(splitlines);
/* history */
myfree(search_h.history_file);
if (search_h.history)
{
for(loop=0; loop<search_h.history_size; loop++)
myfree(search_h.history[loop]);
}
myfree(search_h.history);
myfree(cmdfile_h.history_file);
if (cmdfile_h.history)
{
for(loop=0; loop<cmdfile_h.history_size; loop++)
myfree(cmdfile_h.history[loop]);
}
myfree(cmdfile_h.history);
myfree(color_names);
myfree(window_number);
myfree(subwindow_number);
myfree(defaultcscheme);
myfree(shell);
myfree(ts_format);
myfree(cnv_ts_format);
myfree(statusline_ts_format);
myfree(tail);
myfree(set_title);
myfree(replace_by_markerline);
myfree(line_ts_format);
myfree(n_win_per_col);
myfree(syslog_ts_format);
myfree(global_find);
MEMLOG("finished clean_memory\n");
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1