2

I am creating a replacement memory manager for a school project and I am having trouble with comparing the memory address of a variable in my main.c file to my Node -> starting address, found in my mem.c file. The last 8 digits of the memory address appear to be the same, but the Node -> starting address usually has an extra 4 digits prepended to the memory address.

TLDR I need to test if node -> starting address == memory address of x, and its not working

printf ("var x: %p \n", x ); out = 0x3ee30671
printf("new node start address: %p \n", new_node -> start_address ); out = 0x56223ee30671

main.c

#include <stdio.h>

#define USE_REPLACEMENT_MANAGER 1

#if USE_REPLACEMENT_MANAGER


    #undef malloc 
    #define malloc myMalloc

    #undef free
    #define free myFree

    #include "replacement.h"

#else 

    #include <stdlib.h>
    void* (*f) (size_t s) = malloc;

#endif 

int main( int argc, const char * argv[] ){
    char * x = (char *) malloc(16);
    printf ("var x: %p \n", x );
    free(x);
}

replacement.c

#include <stdio.h>
#include "mem.h"
#include "replacement.h"

void* myMalloc( size_t size){
    return getAddress ( size);
}

void myFree( void * ptr ){
    printf("free address: %p \n", ptr);
    mmFree( ptr );
}

replacement.h

#ifdef REPLACEMENT_MANAGER_INCLUDED
#define REPLACEMENT_MANAGER_INCLUDED

void* myMalloc( size_t size);
void myFree( void * ptr );
void printMyMap ( void );

#endif 

mem.c

#include <stdio.h>
#include <stdlib.h>
#include "mem.h"

typedef struct Node{
    int             type;
    size_t          size;
    char*           start_address;
    struct Node*    next;
    struct Node*    prev;
}Node; 

/*
    * PRIVATE FUNCTIONS
*/
void init_heap( void );

/*
    * PRIVATE FILE LEVEL GLOBAL VARIABLES
*/
#define HEAP_SIZE   1000
char * heap = NULL;
Node* head = NULL;


// FUNCTION THAT ALLOCATES SPACE ON REPLACEMENT HEAP AND RETURNS A POINTER TO THE START ADDRESS
void* getAddress ( size_t size ){
    if ( heap == NULL ){
        init_heap();
    }
    Node * curr = head;
    while ( curr -> next != NULL ){
        if ( ( curr -> size < size ) && ( curr -> type == 0 ) ){
            return curr -> start_address;
        } else curr = curr -> next;
    }
    Node* new_node = (Node *) malloc( sizeof(Node) );
    new_node -> type = 1;
    new_node -> size = size;
    new_node -> start_address = ( curr -> start_address ) + ( curr -> size ) + 1;
    new_node -> next = NULL;
    new_node -> prev = curr;

    curr -> next = new_node;

    printf("new node start address: %p \n", new_node -> start_address );
    return new_node -> start_address;
}

// FUNCTION THAT INITIALIZES REPLACEMENT HEAP AND THE HEAD OF THE LINKED LIST
void init_heap( void ){
    heap = malloc( HEAP_SIZE );
    printf("heap : %p \n",heap);
    head = (Node*) malloc( sizeof(Node) );
    head -> type = 1;
    head -> size = 0;
    head -> start_address = heap;
    head -> next = NULL;
    head -> prev = NULL;
}   

void mmFree( void * ptr ){
    Node * curr = head; 
    printf( "%p \n", (char*) curr -> start_address );
    while ( curr -> next != NULL ){
        if  (  curr -> start_address == ptr ){
            printf( "I NEED THIS TO PRINT" );
            curr -> type = 0;
            break; 
        } else curr = curr -> next;
    }

    Node * p = curr -> prev;
    Node * n = curr -> next;

    if ( ( p != NULL ) && ( p -> type  == 0 ) ){
        curr -> start_address = p -> start_address; 
        curr -> size = ( curr -> size ) + ( p -> size );
        p -> prev -> next = curr;
        curr -> prev = p -> prev;
        free ( p );
    }

    if ( ( n != NULL ) && (n -> type == 0) ){
        curr -> size  = ( curr -> size ) + ( n -> size );
        if ( n -> next != NULL ){
            n -> next -> prev = curr;
            curr -> next = n -> next; 
        }else curr -> next = NULL;
        free ( n );
    }

}

mem.h

#ifdef MEM_INCLUDED
#define MEM_INCLUDED

void mmFree( void * ptr);

void* getAddress ( size_t size );

void printHeapMap( void );

#endif 
  • if you need any more information, or if i excluded any information, let me know. May have missed some stuff when copy and pasting over – Andrew Zelano Feb 22 '19 at 21:59
  • @dbush sorry, i edited the post to include this information. Thank you for letting me know. – Andrew Zelano Feb 22 '19 at 22:02
  • 1
    `myMalloc` is calling `getAddress` twice. – dbush Feb 22 '19 at 22:15
  • @dbrush that was an error from me copying and pasting – Andrew Zelano Feb 22 '19 at 22:27
  • Side note: [don't cast](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) the return of `malloc`. – Phil M Feb 22 '19 at 22:51
  • @Phil M thanks for the tip, but the problem still persists – Andrew Zelano Feb 22 '19 at 22:55
  • How are you compiling and what OS? If I run your code after compiling with `gcc`, I get this: `heap : 0x6000003a0 new node start address: 0x6000003a1 free address: 0x6000003a1 0x6000003a0 ` – bruceg Feb 22 '19 at 23:28
  • @bruceg compile: gcc -g main.c replacement.c mem.c -o mem
    OS: Ubuntu on vitual box VM
    – Andrew Zelano Feb 22 '19 at 23:33
  • why don't you step through the code in gdb and see what the values really are. Maybe to console printing is messed up. – bruceg Feb 22 '19 at 23:37
  • @bruceg also clarification, why is free address printing 2 different addresses for you? EDIT: nvm i see now thats probably the print statement i forgot to take out and that is the address of the heap – Andrew Zelano Feb 22 '19 at 23:38
  • The second address after free is on a separate line. Just bad formatting in comments. It's from the mmFree printf. – bruceg Feb 22 '19 at 23:41
  • @bruceg i just went through line by line with gdb, the memory addresses are all over the place with values that don't make sense. I'm convinced this must be a problem with my VM. Do you know if the code enters the " if ( curr -> start_address == ptr ) " condition in mmFree() on your machine? If it does it must be a problem with my VM. – Andrew Zelano Feb 23 '19 at 00:31
  • What's in the header files? – Shawn Feb 23 '19 at 00:55
  • @Shawn Edited post with header files – Andrew Zelano Feb 23 '19 at 01:05
  • Where are you putting printf("var x:"... from your question? It's not in the code anywhere – Shawn Feb 23 '19 at 01:18
  • @Shawn i cut some stuff out so that the code is easier to read. will edit right now – Andrew Zelano Feb 23 '19 at 01:20
  • Are you sure all these files are being compiled with the same options? – David Schwartz Feb 23 '19 at 01:36
  • @DavidSchwartz Positve. have compiled with "gcc -g main.c replacement.c mem.c -o mem" every time. EDIT: forgot to write gcc -g – Andrew Zelano Feb 23 '19 at 01:40
  • It's not reaching the "I NEED THIS TO PRINT" because (I'm guessing) next is always null. Try calling malloc again before the free. As to why *that* is, we may have to look a bit more... – Shawn Feb 23 '19 at 01:43
  • @Shawn i have another function that loops through the linked list and prints the node's data members that works just fine, with multiple nodes inserted into the list – Andrew Zelano Feb 23 '19 at 01:54

2 Answers2

0

Always enable warnings and read them.

When I compile your code (after adding the missing semicolon in main) using "g++ -std=c11 -Wall -Wextra *.c -o main", I get a lot of warnings about implicit function declarations and conversions of integers to pointers, starting with:

main.c: In function ‘main’:
main.c:9:20: warning: implicit declaration of function ‘myMalloc’; did you mean ‘malloc’? [-Wimplicit-function-declaration]
     #define malloc myMalloc
                    ^
main.c:24:25: note: in expansion of macro ‘malloc’
     char * x = (char *) malloc(16);
                         ^~~~~~
main.c:24:16: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     char * x = (char *) malloc(16);
                ^

In C89, when a function that has not been declared is called, C implicitly assumed a function declaration like extern int func_name();, but if the function definition does not actually use a return type compatible with int, the behavior was undefined. Calling a function that was not declared is ill-formed since C99, but gcc allows it anyway with the old rule and a warning, even when a newer Standard version is specified.

So what's likely happening is that the compiler at some point assumes your functions which actually return pointers are returning int values, resulting in only some of the value bits being used.

So make sure a declaration of every function called is visible, normally by writing and including the correct headers.

aschepler
  • 70,891
  • 9
  • 107
  • 161
0

There's a problem here:

void mmFree( void * ptr ){
    Node * curr = head; 
    printf( "%p \n", (char*) curr -> start_address );
    while ( curr->next != NULL ){
        if  (  curr -> start_address == ptr ){
            printf( "I NEED THIS TO PRINT\n" );
            curr -> type = 0;
            break; 
        } else curr = curr -> next;
    }

Think about the case where you're freeing the last item in the list. The loop will terminate before checking it, because the final item's next pointer will be null. This is not what you want, as the final node does need to be operated on.

The fix is simple, just change it to

void mmFree( void * ptr ){
    Node * curr = head; 
    printf( "%p \n", (char*) curr -> start_address );
    while ( curr != NULL ){
        if  (  curr -> start_address == ptr ){

You will also need to fix up the code after to deal with the case where curr == NULL, which should only be possible if a user erroneously tries to free a pointer not allocated by the malloc replacement, or one that was already freed.

Shawn
  • 621
  • 5
  • 10