Monday's Lecture
The Stack and the Heap
alloc.c
// Introducing `calloc`, `malloc`, and friends.
// 2017-09-04 Jashank Jeremy <{jashankj,z5017851}@cse.unsw.edu.au>
#include <stdio.h>
#include <stdlib.h>
typedef struct _complex {
double re;
double im;
} complex;
// void *calloc (unsigned int nThings, unsigned int thingSize);
int main (int argc, char *argv[]) {
complex c = { 0, 0 };
printf ("c is at %p\n", &c);
printf ("sizeof(c) = %zu\n", sizeof (complex));
/// Some textbooks will make you do an explicit cast; this is
/// forbidden by our style guide, and isn't needed anyway:
//
// complex *cc = (complex *) calloc (1, sizeof (complex));
//
/// Instead, you should do:
complex *cc = calloc (1, sizeof (complex));
/// Allocation _can_ fail. If it does, `malloc` and `calloc` will
/// both return the magic value, `NULL`. On most modern systems,
/// `NULL` is usually zero, but it isn't always guaranteed to be.
///
/// If the allocation fails, you can take two approaches:
///
/// 1. the "I'm trying to develop my code in a hurry" approach:
assert (cc != NULL);
/// 2. the correct approach:
if (cc == NULL) {
printf ("Couldn't allocate memory!\n");
return EXIT_FAILURE;
}
/// A nicer correct approach, which requires you to include
/// `err.h` and `sysexits.h`:
if (cc == NULL) {
err (EX_OSERR, "couldn't allocate memory");
}
printf ("cc is at %p\n", cc);
/// Newton's third law of memory management:
/// "For every allocation, there is an equal and opposite free."
free (cc);
return EXIT_SUCCESS;
}
alloc2.c
// Using allocations to move values around.
// 2017-09-04 Jashank Jeremy <{jashankj,z5017851}@cse.unsw.edu.au>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct _complex {
double re;
double im;
} complex;
complex *readComplexNumbers (int n);
int main (int argc, char *argv[]) {
printf ("# complex numbers: ");
int n;
scanf ("%d", &n);
complex *values = readComplexNumbers (n);
printf ("values[0] = %lf + i %lf\n", values[0].re, values[0].im);
free (values);
/// Say it with me, folks: USE AFTER FREE IS ILLEGAL.
/// `dcc` will catch you if you do this; most compilers will not.
/// This is of the same class of error as using a value
// printf ("values[0] = %lf + i %lf\n", values[0].re, values[0].im);
return EXIT_SUCCESS;
}
complex *readComplexNumbers (int n) {
complex *values = calloc (n, sizeof (complex));
assert (values != NULL);
int i = 0;
while (i < n) {
printf ("x = ");
scanf ("%lf", &(values[i].re));
printf ("y = ");
scanf ("%lf", &(values[i].im));
i++;
}
return values;
}
I’m sorry, I’ll say that again, in case you missed it.
USE AFTER FREE IS ILLEGAL.