1 /* memoryDebug.c - NeonServ v5.3
2 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "memoryDebug.h"
19 #include "memoryInfo.h"
21 #define FILE_NAME_LENGTH 256
22 #define OUTPUT_FILE "leak_info.txt"
32 char file_name[FILE_NAME_LENGTH];
37 struct MemoryNode mem_info;
38 struct MemoryLeak *next;
42 static pthread_mutex_t synchronized;
45 static struct MemoryLeak *ptr_start = NULL;
47 static unsigned int own_allocated_memleaks = 0;
49 static void add_mem_info(void * mem_ref, unsigned int size, const char *file, unsigned int line);
50 static void remove_mem_info(void * mem_ref);
52 void *xmalloc(unsigned int size, const char *file, unsigned int line) {
53 void *ptr = malloc(size);
55 add_mem_info(ptr, size, file, line);
60 void *xcalloc(unsigned int elements, unsigned int size, const char *file, unsigned int line) {
61 void *ptr = calloc(elements, size);
63 add_mem_info(ptr, (elements * size), file, line);
68 char *xstrdup(const char *data, const char *file, unsigned int line) {
69 int len = strlen(data)+1;
70 char *ptr = malloc(len);
73 add_mem_info(ptr, len, file, line);
78 void xfree(void *mem_ref) {
79 remove_mem_info(mem_ref);
84 static void add_mem_info(void *mem_ref, unsigned int size, const char *file, unsigned int line) {
85 SYNCHRONIZE(synchronized);
86 struct MemoryLeak *mem_leak_info = malloc(sizeof(*mem_leak_info));
87 own_allocated_memleaks++;
88 mem_leak_info->mem_info.address = mem_ref;
89 mem_leak_info->mem_info.size = size;
90 strcpy(mem_leak_info->mem_info.file_name, file);
91 mem_leak_info->mem_info.line = line;
92 mem_leak_info->next = ptr_start;
93 ptr_start = mem_leak_info;
94 DESYNCHRONIZE(synchronized);
97 static void remove_mem_info(void *mem_ref) {
98 SYNCHRONIZE(synchronized);
99 struct MemoryLeak *leak_info, *next, *prev = NULL;
100 for(leak_info = ptr_start; leak_info; leak_info = next) {
101 next = leak_info->next;
102 if (leak_info->mem_info.address == mem_ref) {
107 own_allocated_memleaks--;
113 DESYNCHRONIZE(synchronized);
116 void report_mem_leak() {
117 SYNCHRONIZE(synchronized);
118 struct MemoryLeak *leak_info;
119 FILE *fp_write = fopen(OUTPUT_FILE, "wt");
122 if(fp_write != NULL) {
123 sprintf(info, "%s\n", "Memory Leak Summary");
124 fwrite(info, (strlen(info)) , 1, fp_write);
125 sprintf(info, "%s\n", "-----------------------------------");
126 fwrite(info, (strlen(info)) , 1, fp_write);
128 for(leak_info = ptr_start; leak_info != NULL; leak_info = leak_info->next) {
129 sprintf(info, "address : %p\n", leak_info->mem_info.address);
130 fwrite(info, (strlen(info)) , 1, fp_write);
131 sprintf(info, "size : %d bytes\n", leak_info->mem_info.size);
132 fwrite(info, (strlen(info)) , 1, fp_write);
133 sprintf(info, "file : %s\n", leak_info->mem_info.file_name);
134 fwrite(info, (strlen(info)) , 1, fp_write);
135 sprintf(info, "line : %d\n", leak_info->mem_info.line);
136 fwrite(info, (strlen(info)) , 1, fp_write);
137 sprintf(info, "%s\n", "-----------------------------------");
138 fwrite(info, (strlen(info)) , 1, fp_write);
142 DESYNCHRONIZE(synchronized);
145 void initMemoryDebug() {
146 THREAD_MUTEX_INIT(synchronized);
149 struct memoryInfoFiles *getMemoryInfoFiles() {
150 SYNCHRONIZE(synchronized);
151 struct MemoryLeak *leak_info;
152 struct memoryInfoFiles *list = NULL, *element;
153 for(leak_info = ptr_start; leak_info != NULL; leak_info = leak_info->next) {
154 for(element = list; element; element = element->next) {
155 if(!strcmp(leak_info->mem_info.file_name, element->filename)) {
160 element = malloc(sizeof(*element));
161 element->filename = strdup(leak_info->mem_info.file_name);
162 element->allocations = 0;
163 element->allocated = 0;
164 element->next = list;
167 element->allocations += 1;
168 element->allocated += leak_info->mem_info.size;
170 element = malloc(sizeof(*element));
171 element->filename = strdup(__FILE__);
172 element->allocations = own_allocated_memleaks;
173 element->allocated = own_allocated_memleaks * sizeof(struct MemoryLeak);
174 element->next = list;
176 DESYNCHRONIZE(synchronized);
180 void freeMemoryInfoFiles(struct memoryInfoFiles *files) {
181 struct memoryInfoFiles *next;
182 for(;files;files = next) {
184 free(files->filename);
189 struct memoryInfoLines *getMemoryInfoLines(const char *filename) {
190 SYNCHRONIZE(synchronized);
191 struct MemoryLeak *leak_info;
192 struct memoryInfoLines *list = NULL, *element;
193 for(leak_info = ptr_start; leak_info != NULL; leak_info = leak_info->next) {
194 if(stricmp(leak_info->mem_info.file_name, filename)) continue;
195 for(element = list; element; element = element->next) {
196 if(element->line == leak_info->mem_info.line && element->allocate == leak_info->mem_info.size) {
201 element = malloc(sizeof(*element));
202 element->line = leak_info->mem_info.line;
203 element->allocations = 0;
204 element->allocate = leak_info->mem_info.size;
205 element->next = list;
208 element->allocations++;
210 if(!stricmp(filename, __FILE__)) {
211 element = malloc(sizeof(*element));
213 element->allocations = own_allocated_memleaks;
214 element->allocate = sizeof(struct MemoryLeak);
215 element->next = list;
218 DESYNCHRONIZE(synchronized);
222 void freeMemoryInfoLines(struct memoryInfoLines *lines) {
223 struct memoryInfoLines *next;
224 for(;lines;lines = next) {