Сегмент Fualt, когда я передаю ptr функции после того, как я выделил память, но если бы я этого не делал, это было весело?

avatar
W.Cameron
8 апреля 2018 в 00:51
43
1
0

это двойная кольцевая связь. dev_num, blk_num и статус по моему вопросу не выдаются.

   typedef struct buf_node {
    unsigned            dev_num;
    unsigned            blk_num;
    unsigned            status:2;
    struct buf_node     *ptr_prev_free_q;
    struct buf_node     *ptr_next_free_q;
    } stc_buf_header;

это буферный узел, который содержит идентификатор buf_header и поле данных

 typedef struct {
    stc_buf_header      *buf_header;
    stc_mm              *data_area;
    } stc_buffer;

это двойная кольцевая ссылка, которая содержит свободный буферный узел, ожидающий использования (например, UNIX)

typedef struct free_lk_node {
    stc_buffer          *lk_header;
    unsigned            len;
} stc_free_lk;

И, теперь я определяю функцию для инициализации ссылки двойного цикла

int init(stc_buffer *lk_header, unsigned dev_num, unsigned blk_num){

printf("buf_header\t%p\n", lk_header->buf_header);
printf("lk_header\t%p\n", lk_header);

printf("dev_num\t%d\n", lk_header->buf_header->dev_num);
printf("blk_num\t%d\n", lk_header->buf_header->blk_num);

lk_header->buf_header->dev_num = dev_num;
lk_header->buf_header->blk_num = blk_num;
lk_header->buf_header->status = 0x0;
lk_header->buf_header->ptr_next_free_q = lk_header->buf_header;
lk_header->buf_header->ptr_prev_free_q = lk_header->buf_header;
lk_header->data_area->data = -1; // means that this node is header of the          link
}

оператор printf() использовался для отладки, когда я получил эту ошибку.

Хорошо, теперь, если я напишу так в main()

int main(){
    stc_free_lk *link = (stc_free_lk*)malloc(sizeof(stc_free_lk));
    init(link->lk_header, (unsigned)0, (unsigned)0);

    return 0;
}

когда он доходит до точки оператора printf(), возникает ошибка Segment Fualt

Однако, если я напишу так в main()

int main(){
    stc_free_lk link;
    init(link.lk_header, (unsigned)0, (unsigned)0);

    return 0;
}

ВСЕ ОК. ЗАЧЕМ?? меня это смущает...(-o-)#

Источник
Ahmed Masud
8 апреля 2018 в 01:00
0

это на самом деле не в порядке даже во втором случае, это только КАЖЕТСЯ в порядке из-за стека. Попробуйте скомпилировать второй экземпляр с параметром -O2 и посмотрите, не вылетит ли он (вероятно, вылетит).

Ответы (1)

avatar
Pablo
8 апреля 2018 в 01:01
3

Во-первых, используйте %p для печати адресов, а не %d.

А ваша проблема в том, что malloc просто выделяет память, а не инициализирует ее. И ваш вызов malloc только инициализировал память для объекта struct stc_free_lk, он не выделяет память элементам, которые являются указателями, вам также необходимо выделить память для них.

Итак, lk_header->buf_header указывает в никуда, вы не можете разыменовать его, это поведение undefined. То, что вы видите, является классическим случаем неопределенного поведения.

Как я уже сказал, вы должны инициализировать член структуры, прежде чем сможете получить к нему доступ. Вы можете использовать calloc вместо malloc, потому что calloc устанавливает выделенный memory в 0, это помогает при инициализации указателей в структурах.

stc_free_lk *link = calloc(1, sizeof *link);
if(link == NULL)
{
    fprintf(stderr, "Not enough memory\n");
    return 1;
}

link->header = calloc(1, sizeof *link->header);
if(link->header == NULL)
{
    fprintf(stderr, "Not enough memory\n");
    free(link);
    return 1;
}

init(link->lk_header, (unsigned)0, (unsigned)0);
...

Затем в init вы также должны выделить память для lk_header->buf_header и lk_header->data_area и т. д.

Я предлагаю вам написать функцию, которая выделяет всю память для всех указатели, чтобы вам не приходилось выделять память в разных местах. Это делает код трудным для понимания и трудным для поиска ошибок. Также я бы написал destroy функция, которая frees всю выделенную память, снова все в одном месте.

W.Cameron
8 апреля 2018 в 01:06
0

акк, я пытаюсь

W.Cameron
8 апреля 2018 в 01:21
0

Что, если я все еще использую malloc, но указываю, что только что выделено в NULL?

Pablo
8 апреля 2018 в 01:22
0

@ W.Cameron, извините, я не понимаю вашего вопроса.