адрес указателя изменяется при назначении переменной - PullRequest
0 голосов
/ 23 февраля 2019

Я создаю замещающий менеджер памяти для школьного проекта, и у меня возникают проблемы со сравнением адреса памяти переменной в моем файле main.c с моим начальным адресом Node->, найденным в моем файле mem.c.Последние 8 цифр адреса памяти выглядят одинаково, но начальный адрес узла -> обычно имеет дополнительные 4 цифры, добавленные к адресу памяти.

TLDR Мне нужно проверить, если узел -> начальный адрес == адрес памяти x, и он не работает

printf ("var x:% p \ n", x);out = 0x3ee30671
printf («начальный адрес нового узла:% 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);
}

replace.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 );
}

replace.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 

Ответы [ 2 ]

0 голосов
/ 23 февраля 2019

Здесь есть проблема:

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;
    }

Подумайте о случае, когда вы освобождаете последний элемент в списке.Цикл прекратится перед проверкой, потому что следующий указатель последнего элемента будет нулевым.Это не то, что вы хотите, так как последний узел действительно должен быть оперирован.

Исправление простое, просто измените его на

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

Вам также нужно будет исправитькод после, чтобы иметь дело со случаем, когда curr == NULL, что должно быть возможно только в том случае, если пользователь ошибочно пытается освободить указатель, не выделенный заменой malloc, или уже освобожденный указатель.

0 голосов
/ 23 февраля 2019

Всегда включайте предупреждения и читайте их.

Когда я компилирую ваш код (после добавления отсутствующей точки с запятой в main), используя "g ++ -std = c11 -Wall -Wextra *.c -o main ", я получаю много предупреждений о неявных объявлениях функций и преобразованиях целых чисел в указатели, начиная с:

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);
                ^

В C89, когда вызывается функция, которая не была объявлена,C неявно предполагал объявление функции, подобное extern int func_name();, но если определение функции фактически не использует возвращаемый тип, совместимый с int, поведение было неопределенным.Вызов функции, которая не была объявлена, является некорректным с C99, но gcc разрешает это в любом случае со старым правилом и предупреждением, даже если указана более новая версия Standard.

Так что, вероятно, происходит то, что компиляторв какой-то момент предполагается, что ваши функции, которые на самом деле возвращают указатели, возвращают значения int, в результате чего используются только некоторые биты значений.

Поэтому убедитесь, что объявление каждой вызываемой функции является видимым, обычно путем записи ивключая правильные заголовки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...