-
Notifications
You must be signed in to change notification settings - Fork 160
/
malloc.c
181 lines (139 loc) · 4.39 KB
/
malloc.c
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
# malloc
The main way to get new dynamic memory.
Returns a `void*` which can be used for any type.
Typecast from `void*` is implicitly done without warning.
On Linux, implemented with either:
- brk
- mmap
This is one of those library functions which cannot be implemented in pure C itself,
as they require system calls.
See also: glibc non-POSIX alloca which allocates on the stack.
# malloc vs VLA
Dynamic memory has the following characteristics which VLA does not:
- no scope
therefore can be allocated in functions
and returned to caller
- heap much larger than stack
So it is more flexible, at the cost of some runtime speed.
*/
#include "common.h"
int main(void) {
/*
# free
Main way to free dynamic memory after you are done with it.
Freeing a NULL pointer does nothing:
http://stackoverflow.com/questions/1938735/does-freeptr-where-ptr-is-null-corrupt-memory
*/
{
free(NULL);
/*
WARN attempted to free a non heap object.
If this compiled, it could lead to segfault.
*/
{
int i;
/*free(&i);*/
}
/* freeing a pointer twice leads to a segfault */
{
int *ip = malloc(sizeof(int));
free(ip);
/* RUNTIME ERROR: segmentation fault. */
/*free(ip);*/
}
}
/*
# realloc
Change size of allocated memory with malloc.
If you already have allocated some memory, it might be faster to enlargen it
rather than to free it and reallocate.
The library may however choose to move your memory somewhere else if not enough is available
You must use a second pointer to get its value, because in case the reallocation fails,
you still need the old pointer to clear up old memory.
*/
{
size_t bytes = sizeof(int) * 2;
int *is = malloc(bytes);
if (is == NULL) {
printf("malloc failed\n");
} else {
is[1] = 1;
/* You must use a second pointer here. */
int *is2 = realloc(is, sizeof(int) * 4);
if (is2 == NULL) {
printf("realloc failed\n");
} else {
is = is2;
is[3] = 1;
/* Old values are untouched. */
assert(is[1] == 1);
assert(is[3] == 1);
}
free(is);
}
}
/*
# calloc
Like malloc but initializes allocated bytes to zero.
why calloc? <http://www.quora.com/C-programming-language/What-does-the-c-stand-for-in-calloc>
Clear seems most likely.
Takes number of elements and elemetn size separately.
*/
{
int *is = calloc(2, sizeof(int));
if (is == NULL) {
printf("calloc failed\n");
} else {
assert(is[0] == 0);
assert(is[1] == 0);
free(is);
}
}
/*
# malloc multi dimensional arrays
http://stackoverflow.com/questions/1970698/c-malloc-for-two-dimensional-array
For a 2D N x M array, there are two solutions:
- N mallocs of size M
- one malloc of size N x M
In C++, using vectors of vectors is an easier solution.
*/
{
/* One malloc. */
{
}
}
/*
# Allocate too much memory
If you try to allocate too much memory:
- TODO OS kill programs, or malloc fails gracefuly?
Time to try that out!
TODO how to pass more than INT_MAX to malloc to break it? =)
*/
{
if (0) {
size_t n = 1024 * 1024 * 1024;
int *ip = malloc(n);
if (ip == NULL) {
printf("could not allocate %zu bytes", n);
}
free(ip);
}
/*
Allocate 1024 Petabytes of RAM in 1 gb chunks!!!
Someday this will be possible and people will laugh at this...
Generates a segfault today.
*/
if (0) {
const size_t GB = 1 << 30;
for (unsigned int i = 0; i < GB; i++) {
int *ip = malloc(GB);
ip[0] = 0;
if (ip == NULL) {
printf("could not allocate %zu bytes", GB);
}
}
}
}
return EXIT_SUCCESS;
}