Я пока не могу – мне тут valgrind какую-то дичь верещит.

Есть такой вот код:

struct entry_s {

    void (*handler) (void);

    struct entry_s *next;

};

typedef entry_s entry_t;


typedef struct {

    entry_t *first;
    entry_t *last;

} entries_t;


// сюда они добавляются в начале рантайма
static entries_t entries = { NULL, NULL };


// где-то ниже по коду дела

entry_t *entry = entries.first;

while (entry) {

    entry->handler();

    entry = entry->next; // valgrind: Invalid read of size 8
}

Вот скажи мне, как неойтишник, какого хуя ему не нравится?

  • deep-purpleOP
    link
    fedilink
    arrow-up
    0
    ·
    3 years ago

    Ну, раз уж вынес в минимал:

    
    
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    
    ////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////
    
    
    struct entry_s {
    
        int id;
    
        void (*handler) (struct entry_s *entry);
    
        struct entry_s *prev;
        struct entry_s *next;
    
    };
    
    
    typedef struct entry_s entry_t;
    
    
    void
    entry_handler(entry_t *entry)
    {
        char *ptr;
    
    
        printf("handle entry: %p -> %d\n", entry, entry->id);
    
    
        ptr = malloc(1000);
    
        if (NULL == ptr) {
    
            printf("failed to allocate entry handler tmp data\n");
    
            return;
        }
    
    
        memset(ptr, 0, 1000);
    
    
        free(ptr);
    }
    
    
    entry_t *
    entry_create(int id)
    {
        entry_t *entry;
    
    
        entry = malloc(sizeof(entry_t));
    
        if (NULL == entry) {
    
            return NULL;
        }
    
    
        entry->id = id;
    
        entry->handler = entry_handler;
    
        entry->prev = NULL;
        entry->next = NULL;
    
    
        return entry;
    }
    
    
    ////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////
    
    
    typedef struct {
    
        entry_t *first;
        entry_t *last;
    
    } entries_t;
    
    
    void
    entries_add_entry(entries_t *entries, entry_t *entry)
    {
        entry_t *last;
    
    
        last = entries->last;
    
        if (last) {
    
            last->next  = entry;
            entry->prev = last;
    
        } else {
            entries->first = entry;
        }
    
    
        entries->last = entry;
    }
    
    
    void
    entries_remove_entry(entries_t *entries, entry_t  *entry)
    {
        entry_t *prev;
        entry_t *next;
    
    
        prev = entry->prev;
        next = entry->next;
    
    
        if (prev && next) {
    
            prev->next = next;
            next->prev = prev;
    
        } else if (prev) {
    
            prev->next    = NULL;
            entries->last = prev;
    
        } else if (next) {
    
            next->prev     = NULL;
            entries->first = next;
    
        } else {
    
            entries->first = NULL;
            entries->last  = NULL;
        }
    
    
        entry->prev = NULL;
        entry->next = NULL;
    }
    
    
    void
    entries_clear(entries_t *entries)
    {
        entry_t *curr;
        entry_t *next;
    
    
        curr = entries->first;
    
        while (curr) {
    
            next = curr->next;
    
            free(curr);
    
            curr = next;
        }
    
    
        entries->first = NULL;
        entries->last  = NULL;
    }
    
    
    ////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////
    
    
    static entries_t my_entries = { NULL, NULL };
    
    
    ////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////
    
    
    #define ENTRIES_NUM  8
    
    
    int
    main(void)
    {
        entry_t *entry;
    
        int i;
    
    
        // create and add
        for (i = 0; i < ENTRIES_NUM; i++) {
    
    
            entry = entry_create(i);
    
            if (NULL == entry) {
    
                printf("failed to create entry: %d\n", i);
    
                return 1;
            }
    
    
            entries_add_entry(&my_entries, entry);
        }
    
    
        // remove third
        entry = my_entries.first->next->next;
    
        entries_remove_entry(&my_entries, entry);
    
        free(entry);
    
    
        // each
        entry = my_entries.first;
    
        while (entry) {
    
            entry->handler(entry);
    
            entry = entry->next;
        }
    
    
        // clear
        entries_clear(&my_entries);
    
    
        return 0;
    }
    
    
    
    • ThePlayerZero
      link
      fedilink
      arrow-up
      0
      ·
      3 years ago

      так какие у тебя проблемы с этим “минималом”?

      я его скомпилил со всякими санитайзерам и ворнингами, работает вроде всё

      $ gcc -Wall -Wextra -fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=leak -fsanitize=undefined deep-purple.c
      
      $ ./a.out 
      handle entry: 0x603000000010 -> 0
      handle entry: 0x603000000040 -> 1
      handle entry: 0x6030000000a0 -> 3
      handle entry: 0x6030000000d0 -> 4
      handle entry: 0x603000000100 -> 5
      handle entry: 0x603000000130 -> 6
      handle entry: 0x603000000160 -> 7
      

      Чот отдельным минимальным примером не воспроизводится…

      🗿