// CODE
// issues with malloc'd mem
int main1(void) { // memleak (before exit)
  p = malloc(10); // assume malloc succeeded
  // some code
  exit(0);
}

int main2(void) { // memleak (before exit but also right at the "p=NULL" line
  p = malloc(10); // assume malloc succeeded
  // code
  p = NULL; // lost the memory ref, can't deref NULL; can't free -> mem leak
  exit(0); // when process exits, all mem is freed.  But can't rely on that
	   // b/c of long running programs/servers.
}

foo1() // double free
{
  p = malloc(10); // assume succeeded
  // some code
  free(p); // free works/succeeds
  // some more code
  free(p); // most OSs malloc will silently ignore this.  Some will warn or even
	   // crash, esp. if you use a "malloc debugging" library and enable
	   // that functionality.
  // Note: trying to free the same thing twice can be considered "ok" b/c
  // the buffer was already freed before.  But more realistically, it
  // indicates a messy program and possibly a bug (maybe the 2nd free was
  // meant for a different variable?!)
}

// RULE 1: for every malloc there should be EXACTLY one free.
// RULE 2: the free() of a buffer should use the exact addr malloc() returned.

foo2() // mem leak
{
  char *s = malloc(20); // assume succeeded
  strcpy(s, "hello world");
  // some code
  while (*s) // same as s[0]
    printf("%c", *s++); // s++ (inc ptr to point to next addr); then deref s[0]
  // here, 's' has advanced to (near) end of orig allocation, no longer at start
  free(s); // malloc lib won't find entry with CURRENT value of 's', silently
	   // ignore.  Rule: be careful with pointer arithmetic in C.
}

// Q: Why doesn't the malloc library do all these extra checks all the
// time?!
// A: speed, speed, speed!

foo3() // mem leak + wrong free
{
  char *s = malloc(10); // assume succeeded and returned addr 4000
  char *q = malloc(20); // assume succeeded and returned addr 4010
  // some code
  s += 10; // can happen as per example foo2 above.  So "s" points to the
	   // addr of "q"
  free(s); // leaked original S, and worse, freed something else (q)
}

// Lesson: a ptr in C is just a number than can point to any mem addr (a
// number) between 0 and maximum memory size (4GB on 32-bit systems).

foo4() // buffer overflow, writes 0 into MSB or LSB of 'i'
{
  char *s = malloc(10); // assume succeeded and got addr 4000 (up to 4009)
  int *i = malloc(sizeof(int)); // assume this got addr 4010 (up to 4013)
  *i = 1,000,000; // what if this was my bank account balance?!
  strcpy(s, "hello worl"); // write 11 bytes
}
