Warning! This site is under development.
Approximate overview
https://gankra.github.io/blah/c-isnt-a-language/
Whoops. It looks like the Web site didn’t update. Next week!
A simplified version of a buggy program a colleague gave to me.
int
main (int argc, char *argv[])
{
func1 ();
char *stuff2 = (char *) malloc(16 * sizeof (char));
func2 ();
free (stuff2);
return 0;
} // main
Right now, it crashes. (When I was asked about the problem, it was just a standard segfault. Now we get an invalid free error.)
If you don’t call free(stuff2), it works fine, but leaks memory.
If you don’t call func2 (), it doesn’t crash, but doesn’t do what
it’s supposed to do.
func1 and func2 are long enough that you don’t want to read them.
What’s the likely problem? (Or at least a possible problem.)
stuff2. (Although we’ve written an experiment (below) that suggests
that stuff2 retains its contents.)freeing stuff2. Nope, malloc seems
to report that issue.The space given by malloc (or static declarations) is not the same as the space given by strlen.
char str[128];
strcpy (str, "Hello");
// strlen (str) will be 5, but str still occupies 128 bytes.
int
main (int argc, char *argv[])
{
func1 ();
char *stuff2 = (char *) malloc(16 * sizeof (char));
strcpy (stuff2, "Example");
func2 ();
printf ("[%s]\n", stuff2);
free (stuff2);
return 0;
} // main
malloc and freeTPS
How would you implement them?
brk or sbrk.malloc and free.You have a free list, which contains all of the available chunks of memory. When you allocate memory, you either
That is, malloc has a hidden data structure that contains one or more
lists of the chunks it can return. For each chunk, it stores the size.
One way to do free: (a) Verify that it’s malloced (e.g., by checking where in memory it is) and (b) add it back to the list. Maybe (c) clear it out.
When we call free, how does it know how much space the block took up
in order to put it back into the list?
TPS
What tends to cause segfaults in (your) C programs?
int *ip;
int i;
ip = &i;
// or
ip = (int *) i; // Tihs is invalid
What errors do novices tend to make with malloc and free?
int *ints = malloc(16) vs int *ints = malloc (16 * sizeof (int))
struct node *np = malloc(sizeof (struct node *));struct node *np = malloc(sizeof (struct node));How do you diagnose or avoid memory issues in C programs?
void
store(int *arr, int pos, int size, int val)
{
if (pos < 0) {
fprintf (stderr, "Dear idiot, you should not use negative array indices.\n");
}
else if (pos >= size) {
fprintf (stderr, "Out of limits!");
}
else {
arr[pos] = val;
}
} // store
-fsanitize=address as a flag
and it will report “all” memory errors.valgrindHistoric approach (using gcc): valgrind (rhymes with wind)
Modern (clang) approach): -f sanitize=address
Some sample problems and what we see …