выравнивание памяти 64 бит - PullRequest
2 голосов
/ 07 августа 2011

Я играл с C сегодня, и у меня никогда не было возможности поиграть, то есть использовать структуру с указателями на функции ... ну, все прошло хорошо, пока я не начал получать какую-то странную ошибку, когда Я чистил все это (кстати: я компилировал в x86_64 arch, в Mac) Взглянув и посмотрев, я понял, что это выравнивание памяти в структуре node_vtable.

В i386 все работает нормально .. никаких проблем вообще. Однако, как я сказал в x86_64, это не работает.

/* NOT WORKING */
struct node_vtable {
    void    (*add_node)     (linked_list *, node *);
    node *  (*create_node)  (linked_list *, float, int, int );
    void    (*print)        (linked_list *llist);

};

/* WORKING */
struct node_vtable {
    void    (*print)        (linked_list *llist);
    void    (*add_node)     (linked_list *, node *);
    node *  (*create_node)  (linked_list *, float, int, int );  

};

Теперь я исправил это перемещение указателя node * (*create_node) (linked_list *, float, int, int ); в конец структуры, так как он имеет размер 24 байта, который является самым большим в этой структуре. Тем не менее, я действительно думаю, что наверняка есть более элегантное решение, а также я ищу четкое объяснение. Следовательно, если кто-то может дать подсказку или какое-то объяснение, это было бы здорово;) .... поскольку мой мозг сейчас действительно застрял:)

Весь код:

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

struct node {
    int     id;
    int     var;                  
    float   f_var;
    struct  node *next;
};
typedef struct node node;
typedef struct linked_list linked_list;

/* Structs */
struct node_vtable {
    void    (*add_node)     (linked_list *, node *);
    node *  (*create_node)  (linked_list *, float, int, int );
    void    (*print)        (linked_list *llist);

};

struct linked_list {
    /************************/
    node *head;
    node *tail;
    /************************/
    node *data;
    /* VTable to Methods*/
    struct node_vtable *method;
};


/*Prototypes*/
linked_list *constructor_linked_list();

void print(linked_list *llist);
void add_node(linked_list *this, node *node);
node *create_node(linked_list *this, float f_var, int var, int _id);


/***************/
linked_list *constructor_linked_list() {
    printf("calling constructor_linked_list...\n");
    linked_list *this = (linked_list *)malloc(sizeof(linked_list));

    this->head = NULL;
    this->tail = NULL;
    this->method = NULL;
    this->method = (struct node_vtable *)malloc(sizeof(struct node_vtable *));

    this->method->print         = &print;
    this->method->add_node      = &add_node;
    this->method->create_node   = &create_node;

    return this;
}

void print(linked_list *llist) {
    printf("calling print ...\n");
    node *iter = llist->head;
    while (iter){
        printf("\tnode %d\n", iter->id);
        iter = iter->next;
    }
}

void add_node(linked_list *this, node *node) {
    printf("calling add_node_...\n");
    if (this->head == NULL) {
        node->next = NULL;
        this->head = node;
        this->tail = node;   
    } else {
        node->next = NULL;
        this->tail->next = node;
        this->tail = node; 
    }
}

node *create_node(linked_list *this, float f_var, int var, int _id) {
    printf("calling create_node ...%d\n",(int)sizeof(struct node_vtable));
    node *ret_node = (node *)malloc(sizeof(struct node));  
    ret_node->var = var;   
    ret_node->id = _id;
    ret_node->f_var = f_var; 
    ret_node->next = NULL;

    return ret_node;
}

int main(int argc, char *argv[]) {  

    linked_list *obj = constructor_linked_list();
    int i;
    for (i = 0; i < 10; i++) {
        obj->method->add_node(obj, create_node(obj, 5.0, 3, i));
    }
    obj->method->print(obj);
    return EXIT_SUCCESS;
}

Приветствия

Ответы [ 2 ]

7 голосов
/ 07 августа 2011

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

Эта строка:

 this->method = (struct node_vtable *)malloc(sizeof(struct node_vtable *));

должна быть:

 this->method = (struct node_vtable *)malloc(sizeof(struct node_vtable));

К сожалению, я не могу проверить, решает ли это проблему (обычный cygwin x86 здесь), если нет, то обязательно проверьте его с помощью valgrind.

4 голосов
/ 07 августа 2011

У вас, похоже, опечатка:

this->method = (struct node_vtable *)malloc(sizeof(struct node_vtable *));

должно быть:

this->method = (struct node_vtable *)malloc(sizeof(struct node_vtable));
...