forked from freewilll/wcc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmemory.c
More file actions
137 lines (106 loc) · 3.23 KB
/
memory.c
File metadata and controls
137 lines (106 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __linux__
#include <malloc.h>
#endif
#include "wcc.h"
static long total_allocation = 0;
static long peak_allocation = 0;
static long current_allocation = 0;
static int allocation_count = 0;
static int free_count = 0;
#ifndef __linux__
// malloc_usable_size is linux specific
size_t malloc_usable_size(void * ptr) {
return 0;
}
#endif
static void add_to_allocation(size_t size) {
current_allocation += size;
total_allocation += size;
if (current_allocation > peak_allocation) peak_allocation = current_allocation;
allocation_count++;
}
static void remove_from_allocation(size_t size) {
current_allocation -= size;
free_count++;
}
// Wrapper around malloc that exits if malloc fails
void *wmalloc(size_t size) {
if (!size) return NULL;
void *result = malloc(size);
if (!result) {
printf("Failed to malloc %ld bytes\n", size);
exit(1);
}
add_to_allocation(malloc_usable_size(result));
return result;
}
// Wrapper around realloc that exits if realloc fails
void *wrealloc(void *ptr, size_t size) {
remove_from_allocation(malloc_usable_size(ptr));
void *result = realloc(ptr, size);
if (!result) {
printf("Failed to realloc %ld bytes\n", size);
exit(1);
}
add_to_allocation(malloc_usable_size(result));
return result;
}
// Wrapper around calloc that exits if calloc fails
void *wcalloc(size_t nitems, size_t size) {
if (!size || !nitems) return NULL;
void *result = calloc(nitems, size);
if (!result) {
printf("Failed to calloc %ld items of %ld bytes\n", nitems, size);
exit(1);
}
add_to_allocation(malloc_usable_size(result));
return result;
}
// Wrapper around strdup that exits if strdup fails
char *wstrdup(const char *str) {
char *ptr = strdup(str);
if (!ptr) {
printf("Failed to strdup %s\n", str);
exit(1);
}
add_to_allocation(malloc_usable_size(ptr));
return ptr;
}
// Wrapper around free
void wfree(void *ptr) {
if (!ptr) return;
remove_from_allocation(malloc_usable_size(ptr));
free(ptr);
}
static void print_human_readable_value(long value) {
if (value < 0) {
printf("-");
value = -value;
}
char buffer[128];
sprintf(buffer, "%ld", value);
int len = strlen(buffer);
for (int i = 0; i < len; i++) {
printf("%d", buffer[i] - '0');
int remaining = len - i;
if (remaining >= 3 && ((remaining - 1) % 3 == 0)) printf(",");
}
}
void process_memory_allocation_stats(void) {
if (print_heap_usage || (fail_on_leaked_memory && current_allocation)) {
printf("In use at exit: ");
print_human_readable_value(current_allocation); printf(" bytes\n");
printf("Total heap usage: ");
print_human_readable_value(allocation_count); printf(" allocs, ");
print_human_readable_value(free_count); printf(" frees, ");
print_human_readable_value(total_allocation); printf(" bytes allocated, ");
print_human_readable_value(peak_allocation); printf(" bytes peak usage\n");
}
if (fail_on_leaked_memory && current_allocation) {
printf("Memory has been leaked.\n");
exit(1);
}
}