CS241

Memory

Question 1

Allocation!

Question 2 - Formulas

I know that you don’t like these formulas or this pseudocode. It helps a lot though to write out the pseudocode and think about all of the possible outcomes

Lab Time!

Why am I doing this lab?

  • Learn how Valgrind works
  • Learn memory layout and how malloc/free works
  • How does free know how many bytes it has to free?

Memory in C

So we are going to do a little review of memory and offsets in C. There are a fair amount of you which haven’t taken 233 (Which is okay!) but we need to get you up to speed on the prerequisites. So here is a struct.

How we are going to lay this out in memory is with offsets. We will malloc a certain amount of space and each of the variables will take up space right next to each other and take up as much space as the variable is defined to in the standard.

So how does this look with some actually simple code?

typedef struct{
    int n1;
    float n2;
    char st[10];
} contact;

int main(){
    contact bhuvan;
    printf("Contact address:\t%p\n", &bhuvan);
    printf("Contact n1 location:\t%p\n", &bhuvan.n1);
    printf("Contact n2 location:\t%p\n", &bhuvan.n2);
    printf("Contact nst location:\t%p\n", &bhuvan.st);
    return 0;
}
$ gcc main.c -o stack
$ ./stack
    Contact address:        0x7ffcc8568b40
    Contact n1 location:    0x7ffcc8568b40
    Contact n2 location:    0x7ffcc8568b44
    Contact nst location:   0x7ffcc8568b48

So what does this mean?

GCC or Clang or whatever compiler you use calculates offsets form the base address of your contact (in this case bhuvan). It knows that the first element is at offset 0 and the second element is at offset +4 and the third element is at offset +8 from your starting address.

Cool So What does this have to do with Malloc?

typedef struct{
    int n1;
    float n2;
    char st[10];
} contact;

int main(){
    contact* bhuvan = malloc(sizeof(*bhuvan));
    printf("Contact address:\t%p\n", bhuvan);
    printf("Contact n1 location:\t%p\n", &bhuvan->n1);
    printf("Contact n2 location:\t%p\n", &bhuvan->n2);
    printf("Contact nst location:\t%p\n", &bhuvan->st);
    free(bhuvan);
    return 0;
}
$ gcc malloc-main.c -o malloc-main
$ ./malloc-main
    Contact address:        0x1bcd010
    Contact n1 location:    0x1bcd010
    Contact n2 location:    0x1bcd014
    Contact nst location:   0x1bcd018

Right But What Does this have to do with our Mini-Malloc?

What’s Pointer Arithmetic?

#include <stdio.h>
#define print_increment(var_name) \
do { \
    printf(#var_name "'s address before: %p\n", var_name); \
    printf(#var_name "'s address after + 1: %p\n\n", var_name+1); \
} \
while(0)
int main(){
    char *char_ptr;
    int *int_ptr;
    double *double_ptr;
    void *void_ptr;

    print_increment(char_ptr);
    print_increment(int_ptr);
    print_increment(double_ptr);
    print_increment(void_ptr);
    return 0;
}
$ gcc pointer.c -O0 -o pointer
$ ./pointer
    char_ptr's address before: 0x400600
    char_ptr's address after + 1: 0x400601

    int_ptr's address before: 0x400430
    int_ptr's address after + 1: 0x400434

    double_ptr's address before: 0x7ffe282f0b20
    double_ptr's address after + 1: 0x7ffe282f0b28

    void_ptr's address before: (nil)
    void_ptr's address after + 1: 0x1

Hey! Shouldn’t we not be able to do arithmetic with void pointers?

Technically yeah, but gcc and clang treats it as a char*. In short, don’t do it because the standard doesn’t gaurentee it.

The Big Picture

Hints

  • meta_data *head: head for linked-list
  • total_memory_requested: keep track of bytes used
  • total_memory_freed: keep track of bytes freed
  • Think about how to create a linked-list and insert/remove
  • Insert has to be constant time
  • Have to catch bad calls to free (like double frees)

Questions?

Authors: Steve & Bhuvan