| @@ -198,17 +198,10 @@ PUB_FUNC char *tcc_fileextension (const char *name) · 197 unmodified lines |
| 198 | #undef malloc | 198 | #undef malloc |
| 199 | #undef realloc | 199 | #undef realloc |
| 200 | | 200 | |
| 201 | #ifdef MEM_DEBUG | 201 | #ifndef MEM_DEBUG |
| 202 | ST_DATA int mem_cur_size; | | |
| 203 | ST_DATA int mem_max_size; | | |
| 204 | unsigned malloc_usable_size(void*); | | |
| 205 | #endif | | |
| 206 | | 202 | |
| 207 | PUB_FUNC void tcc_free(void *ptr) | 203 | PUB_FUNC void tcc_free(void *ptr) |
| 208 | { | 204 | { |
| 209 | #ifdef MEM_DEBUG | | |
| 210 | mem_cur_size -= malloc_usable_size(ptr); | | |
| 211 | #endif | | |
| 212 | free(ptr); | 205 | free(ptr); |
| 213 | } | 206 | } |
| 214 | | 207 | |
| @@ -218,11 +211,6 @@ PUB_FUNC void *tcc_malloc(unsigned long size) · 3 unmodified lines |
| 218 | ptr = malloc(size); | 211 | ptr = malloc(size); |
| 219 | if (!ptr && size) | 212 | if (!ptr && size) |
| 220 | tcc_error("memory full (malloc)"); | 213 | tcc_error("memory full (malloc)"); |
| 221 | #ifdef MEM_DEBUG | | |
| 222 | mem_cur_size += malloc_usable_size(ptr); | | |
| 223 | if (mem_cur_size > mem_max_size) | | |
| 224 | mem_max_size = mem_cur_size; | | |
| 225 | #endif | | |
| 226 | return ptr; | 214 | return ptr; |
| 227 | } | 215 | } |
| 228 | | 216 | |
| @@ -237,18 +225,9 @@ PUB_FUNC void *tcc_mallocz(unsigned long size) · 8 unmodified lines |
| 237 | PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size) | 225 | PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size) |
| 238 | { | 226 | { |
| 239 | void *ptr1; | 227 | void *ptr1; |
| 240 | #ifdef MEM_DEBUG | | |
| 241 | mem_cur_size -= malloc_usable_size(ptr); | | |
| 242 | #endif | | |
| 243 | ptr1 = realloc(ptr, size); | 228 | ptr1 = realloc(ptr, size); |
| 244 | if (!ptr1 && size) | 229 | if (!ptr1 && size) |
| 245 | tcc_error("memory full (realloc)"); | 230 | tcc_error("memory full (realloc)"); |
| 246 | #ifdef MEM_DEBUG | | |
| 247 | /* NOTE: count not correct if alloc error, but not critical */ | | |
| 248 | mem_cur_size += malloc_usable_size(ptr1); | | |
| 249 | if (mem_cur_size > mem_max_size) | | |
| 250 | mem_max_size = mem_cur_size; | | |
| 251 | #endif | | |
| 252 | return ptr1; | 231 | return ptr1; |
| 253 | } | 232 | } |
| 254 | | 233 | |
| @@ -262,11 +241,187 @@ PUB_FUNC char *tcc_strdup(const char *str) · 7 unmodified lines |
| 262 | | 241 | |
| 263 | PUB_FUNC void tcc_memstats(void) | 242 | PUB_FUNC void tcc_memstats(void) |
| 264 | { | 243 | { |
| 265 | #ifdef MEM_DEBUG | | |
| 266 | printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size); | | |
| 267 | #endif | | |
| 268 | } | 244 | } |
| 269 | | 245 | |
| | 246 | #else |
| | 247 | |
| | 248 | #define MEM_DEBUG_MAGIC1 0xFEEDDEB1 |
| | 249 | #define MEM_DEBUG_MAGIC2 0xFEEDDEB2 |
| | 250 | #define MEM_DEBUG_FILE_LEN 15 |
| | 251 | |
| | 252 | struct mem_debug_header { |
| | 253 | size_t magic1; |
| | 254 | size_t size; |
| | 255 | struct mem_debug_header *prev; |
| | 256 | struct mem_debug_header *next; |
| | 257 | size_t line_num; |
| | 258 | char file_name[MEM_DEBUG_FILE_LEN + 1]; |
| | 259 | size_t magic2; |
| | 260 | }; |
| | 261 | |
| | 262 | typedef struct mem_debug_header mem_debug_header_t; |
| | 263 | |
| | 264 | static mem_debug_header_t *mem_debug_chain; |
| | 265 | static size_t mem_cur_size; |
| | 266 | static size_t mem_max_size; |
| | 267 | |
| | 268 | PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line) |
| | 269 | { |
| | 270 | void *ptr; |
| | 271 | mem_debug_header_t *header; |
| | 272 | |
| | 273 | ptr = malloc(sizeof(mem_debug_header_t) + size); |
| | 274 | if (!ptr) |
| | 275 | tcc_error("memory full (malloc)"); |
| | 276 | |
| | 277 | mem_cur_size += size; |
| | 278 | if (mem_cur_size > mem_max_size) |
| | 279 | mem_max_size = mem_cur_size; |
| | 280 | |
| | 281 | header = (mem_debug_header_t *)ptr; |
| | 282 | |
| | 283 | header->magic1 = MEM_DEBUG_MAGIC1; |
| | 284 | header->magic2 = MEM_DEBUG_MAGIC2; |
| | 285 | header->size = size; |
| | 286 | header->line_num = line; |
| | 287 | |
| | 288 | strncpy(header->file_name, file, MEM_DEBUG_FILE_LEN); |
| | 289 | header->file_name[MEM_DEBUG_FILE_LEN] = 0; |
| | 290 | |
| | 291 | header->next = mem_debug_chain; |
| | 292 | header->prev = NULL; |
| | 293 | |
| | 294 | if (header->next) |
| | 295 | header->next->prev = header; |
| | 296 | |
| | 297 | mem_debug_chain = header; |
| | 298 | |
| | 299 | ptr = (char *)ptr + sizeof(mem_debug_header_t); |
| | 300 | return ptr; |
| | 301 | } |
| | 302 | |
| | 303 | PUB_FUNC void tcc_free_debug(void *ptr) |
| | 304 | { |
| | 305 | mem_debug_header_t *header; |
| | 306 | |
| | 307 | if (!ptr) |
| | 308 | return; |
| | 309 | |
| | 310 | ptr = (char *)ptr - sizeof(mem_debug_header_t); |
| | 311 | header = (mem_debug_header_t *)ptr; |
| | 312 | if (header->magic1 != MEM_DEBUG_MAGIC1 || |
| | 313 | header->magic2 != MEM_DEBUG_MAGIC2 || |
| | 314 | header->size == (size_t)-1 ) |
| | 315 | { |
| | 316 | tcc_error("tcc_free check failed"); |
| | 317 | } |
| | 318 | |
| | 319 | mem_cur_size -= header->size; |
| | 320 | header->size = (size_t)-1; |
| | 321 | |
| | 322 | if (header->next) |
| | 323 | header->next->prev = header->prev; |
| | 324 | |
| | 325 | if (header->prev) |
| | 326 | header->prev->next = header->next; |
| | 327 | |
| | 328 | if (header == mem_debug_chain) |
| | 329 | mem_debug_chain = header->next; |
| | 330 | |
| | 331 | free(ptr); |
| | 332 | } |
| | 333 | |
| | 334 | |
| | 335 | PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line) |
| | 336 | { |
| | 337 | void *ptr; |
| | 338 | ptr = tcc_malloc_debug(size,file,line); |
| | 339 | memset(ptr, 0, size); |
| | 340 | return ptr; |
| | 341 | } |
| | 342 | |
| | 343 | PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line) |
| | 344 | { |
| | 345 | mem_debug_header_t *header; |
| | 346 | int mem_debug_chain_update = 0; |
| | 347 | |
| | 348 | if (!ptr) { |
| | 349 | ptr = tcc_malloc_debug(size, file, line); |
| | 350 | return ptr; |
| | 351 | } |
| | 352 | |
| | 353 | ptr = (char *)ptr - sizeof(mem_debug_header_t); |
| | 354 | header = (mem_debug_header_t *)ptr; |
| | 355 | if (header->magic1 != MEM_DEBUG_MAGIC1 || |
| | 356 | header->magic2 != MEM_DEBUG_MAGIC2 || |
| | 357 | header->size == (size_t)-1 ) |
| | 358 | { |
| | 359 | check_error: |
| | 360 | tcc_error("tcc_realloc check failed"); |
| | 361 | } |
| | 362 | |
| | 363 | mem_debug_chain_update = (header == mem_debug_chain); |
| | 364 | |
| | 365 | mem_cur_size -= header->size; |
| | 366 | ptr = realloc(ptr, sizeof(mem_debug_header_t) + size); |
| | 367 | if (!ptr) |
| | 368 | tcc_error("memory full (realloc)"); |
| | 369 | |
| | 370 | header = (mem_debug_header_t *)ptr; |
| | 371 | if (header->magic1 != MEM_DEBUG_MAGIC1 || |
| | 372 | header->magic2 != MEM_DEBUG_MAGIC2) |
| | 373 | { |
| | 374 | goto check_error; |
| | 375 | } |
| | 376 | |
| | 377 | mem_cur_size += size; |
| | 378 | if (mem_cur_size > mem_max_size) |
| | 379 | mem_max_size = mem_cur_size; |
| | 380 | |
| | 381 | header->size = size; |
| | 382 | if (header->next) |
| | 383 | header->next->prev = header; |
| | 384 | |
| | 385 | if (header->prev) |
| | 386 | header->prev->next = header; |
| | 387 | |
| | 388 | if (mem_debug_chain_update) |
| | 389 | mem_debug_chain = header; |
| | 390 | |
| | 391 | ptr = (char *)ptr + sizeof(mem_debug_header_t); |
| | 392 | return ptr; |
| | 393 | } |
| | 394 | |
| | 395 | PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line) |
| | 396 | { |
| | 397 | char *ptr; |
| | 398 | ptr = tcc_malloc_debug(strlen(str) + 1, file, line); |
| | 399 | strcpy(ptr, str); |
| | 400 | return ptr; |
| | 401 | } |
| | 402 | |
| | 403 | PUB_FUNC void tcc_memstats(void) |
| | 404 | { |
| | 405 | if (mem_cur_size) { |
| | 406 | mem_debug_header_t *header = mem_debug_chain; |
| | 407 | |
| | 408 | fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n", |
| | 409 | mem_cur_size, mem_max_size); |
| | 410 | |
| | 411 | while (header) { |
| | 412 | fprintf(stderr, " file %s, line %u: %u bytes\n", |
| | 413 | header->file_name, header->line_num, header->size); |
| | 414 | header = header->next; |
| | 415 | } |
| | 416 | } |
| | 417 | } |
| | 418 | |
| | 419 | #undef MEM_DEBUG_MAGIC1 |
| | 420 | #undef MEM_DEBUG_MAGIC2 |
| | 421 | #undef MEM_DEBUG_FILE_LEN |
| | 422 | |
| | 423 | #endif |
| | 424 | |
| 270 | #define free(p) use_tcc_free(p) | 425 | #define free(p) use_tcc_free(p) |
| 271 | #define malloc(s) use_tcc_malloc(s) | 426 | #define malloc(s) use_tcc_malloc(s) |
| 272 | #define realloc(p, s) use_tcc_realloc(p, s) | 427 | #define realloc(p, s) use_tcc_realloc(p, s) |