LINUX.ORG.RU

valgrind ругается на запись в структуру

 ,


0

2

Всем добрый вечер.

Имеем: связанный список, например такой структуры:

typedef struct t_t_buffer_list_data {
  uint8_t *data;
  uint16_t data_len;
  uint32_t id;
  
  struct t_t_buffer_list_data *next;
  
} t_buffer_list_data;
И вторую структуру:
typedef struct {
  t_buffer_list_data *first; //указатель на первую структуру в списке
  t_buffer_list_data *last; // соответственно на последную
  
  uint32_t count;     //общее кол-во структур
} t_buffer_list_main;

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

buffer_list_main t_buffer_list_main;
Итак, в общем во всей работе с этими списками есть такая функция, которая в переменной buffer_list_main меняет значение указателя на последний элемент в списке:
t_buffer_list_data *buffer_list_add_item(t_buffer_list_data * last, uint8_t *data, uint16_t data_size, uint32_t id) {
  t_buffer_list_data *buffer_list_data;

  buffer_list_main.count++;
  buffer_list_data = (t_buffer_list_data*)malloc(sizeof(t_buffer_list_data));
  buffer_list_data->data = malloc(data_size);
  buffer_list_data->next = NULL;
  buffer_list_data->data_len = data_size;
  buffer_list_data->session_id = session_id;

  memcpy(buffer_list_data->data, data, data_size);
  
  if (buffer_list_main.last != NULL) {
    buffer_list_main.last->next = buffer_list_data;
  }

  return buffer_list_data;
}
НО! valgrind ругается на эту строчку:
buffer_list_main.last->next = buffer_list_data;
пишет: Invalid write of size 8 at 0x40577F: buffer_list_add_item (buffer_list.c:53)

Там дальше и другие есть названия функций по списку... но трабла именно в этом присвоении - коментил ругаться valgrind перестает. В общем, решил убрать buffer_list_main и вынести из структуры указатели на первый и последний элементы, ругань прошла. Может кто подскажет из-за чего такое происходит? выравнивание делал на всякий случай. Заранее благодарен! И да система убунту 12.01 gcc 4,6,3.


buffer_list_main.last не инициализировано?

i-rinat ★★★★★
()
buffer_list_main t_buffer_list_main;

может наоборот?

anonymous
()

Не понятно 2 вещи

Как у тебя инициализируется указатель buffer_list_main.last (и вообще buffer_list_main)

И что будет есть он НЕ NULL

И это вще что такое? buffer_list_main t_buffer_list_main; У тебя ж t_buffer_list_main это тип.

anonymous
()
Ответ на: комментарий от anonymous

И это вще что такое? buffer_list_main t_buffer_list_main; У тебя ж t_buffer_list_main это тип.

Да, опечатался.

t_buffer_list_main buffer_list_main 

Инициализируется при старте модуля, указателям присваивается NULL, собственно как и сейчас вынесеным из структуры двум указателям. Из всех изменений только вынес указатели и все... если раньше было так:

 buffer_list_main.last = new_list; 
То теперь
last = new_list;

hound
() автор топика
Ответ на: комментарий от hound

выкатывай минимальный код, на который ВГ ругается.

anonymous
()

Или показывай что здесь не правильно работает

#!/bin/bash

rm -f a.out
gcc -x c -g - <<EOF
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

typedef struct t_t_buffer_list_data {
  uint8_t *data;
  uint16_t data_len;
  uint32_t id;

  struct t_t_buffer_list_data *next;

} t_buffer_list_data;

typedef struct {
  t_buffer_list_data *first; //указатель на первую структуру в списке
  t_buffer_list_data *last; // соответственно на последную

  uint32_t count;     //общее кол-во структур
} t_buffer_list_main;

t_buffer_list_main buffer_list_main = {
  .first = NULL,
  .last = NULL,
  .count = 0
};

t_buffer_list_data *buffer_list_add_item(t_buffer_list_data * last, uint8_t *data, uint16_t data_size, uint32_t id) {
  t_buffer_list_data *buffer_list_data;

  buffer_list_main.count++;
  buffer_list_data = (t_buffer_list_data*)malloc(sizeof(t_buffer_list_data));
  buffer_list_data->data = malloc(data_size);
  buffer_list_data->next = NULL;
  buffer_list_data->data_len = data_size;
  buffer_list_data->id = id;

  memcpy(buffer_list_data->data, data, data_size);

  if (buffer_list_main.last != NULL) {
    buffer_list_main.last->next = buffer_list_data;
  }

  return buffer_list_data;
}

int main() {
  uint8_t data[5] = {1,2,3,4,5};
  t_buffer_list_data *a = buffer_list_add_item(NULL, data, 5, 6);
  free(a->data);
  free(a);
  return 0;
}
EOF

valgrind --leak-check=full ./a.out

anonymous
()
Ответ на: комментарий от anonymous
Invalid write of size 8
==7001==    at 0x40577F: buffer_list_add_item (buffer_list.c:53)
==7001==    by 0x40586D: buffer_list_put_item (buffer_list.c:83)
==7001==    by 0x4059E7: buffer_list_add_line (buffer_list.c:131)
==7001==    by 0x4041D7: kasbi_data_process (kasbi_p.c:73)
==7001==    by 0x402FAA: on_buffer_read (server.c:54)
==7001==    by 0x4E4F519: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.0.so.5.1.9)
==7001==    by 0x4E44F23: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.0.so.5.1.9)
==7001==    by 0x403717: main (server.c:227)
==7001==  Address 0x5b9aa2e is 14 bytes inside a block of size 22 free'd
==7001==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7001==    by 0x405806: buffer_list_free_item (buffer_list.c:72)
==7001==    by 0x405956: buffer_list_get_item (buffer_list.c:115)
==7001==    by 0x4046F5: check_send_data (thread_ex.c:131)
==7001==    by 0x4048AD: thread_ex_func (thread_ex.c:184)
==7001==    by 0x5953181: start_thread (pthread_create.c:312)
==7001==    by 0x567FFBC: clone (clone.S:111)

Функции:

t_buffer_list_data *buffer_list_add_item(t_buffer_list_data * last, uint8_t *data, uint16_t data_size, uint32_t session_id) {
  t_buffer_list_data *buffer_list_data;

  buffer_list_main.count++;
  buffer_list_data = (t_buffer_list_data*)malloc(sizeof(t_buffer_list_data));
  buffer_list_data->data = malloc(data_size);
  buffer_list_data->next = NULL;
  buffer_list_data->data_len = data_size;
  buffer_list_data->session_id = session_id;

  memcpy(buffer_list_data->data, data, data_size);
  
  if (buffer_list_main.last != NULL) {
    buffer_list_main.last->next = buffer_list_data;
  }

  return buffer_list_data;
}

void buffer_list_put_item(uint8_t *data, uint16_t data_size, uint32_t session_id) {
  buffer_list_lock();
  
  if (buffer_list_main.first == NULL) {
    buffer_list_main.first = buffer_list_add_item(NULL, data, data_size, session_id);
    buffer_list_main.last = buffer_list_main.first;
  } else {
    buffer_list_main.last = buffer_list_add_item(buffer_list_main.last, data, data_size, session_id);
  }
  
  buffer_list_unlock();
}

void buffer_list_add_line(char * str, uint32_t session_id) {
  buffer_list_put_item(str, strlen(str) + 1, session_id);
  
 }


hound
() автор топика
Ответ на: комментарий от hound

В заголовочнике:

#pragma pack(push)
#pragma pack(1)
typedef struct t_t_buffer_list_data {
  uint8_t *data;
  uint16_t data_len;
  uint32_t session_id;
  
  struct t_t_buffer_list_data *next;
  
} t_buffer_list_data;

typedef struct {
  t_buffer_list_data *first;
  t_buffer_list_data *last;
  
  uint32_t count;
} t_buffer_list_main;
#pragma pack(pop)

hound
() автор топика
Ответ на: комментарий от hound

с buffer_list_put_item тоже не канает. ибо

==29999== HEAP SUMMARY:
==29999==     in use at exit: 0 bytes in 0 blocks
==29999==   total heap usage: 2 allocs, 2 frees, 29 bytes allocated
==29999== 
==29999== All heap blocks were freed -- no leaks are possible
==29999== 
==29999== For counts of detected and suppressed errors, rerun with: -v
==29999== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

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

anonymous
()
Ответ на: комментарий от anonymous

buffer_list_lock buffer_list_unlock

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

hound
() автор топика
Ответ на: комментарий от hound

если разница тащемто. И не факт, что у тебя при вынесении указателей из структуры нет бага. Ты его просто замазал.

anonymous
()
Ответ на: комментарий от hound

не гадай, выкатывай маломальски собирающийся код

anonymous
()
Ответ на: комментарий от anonymous

А в чем разница тогда указателей в структуре и вне ее?

И не факт, что у тебя при вынесении указателей из структуры нет бага. Ты его просто замазал.

valgrind больше не ругается, да и пока не прога не крешилась, раньше могла упасть.

hound
() автор топика
Ответ на: комментарий от hound

А в чем разница тогда указателей в структуре и вне ее?

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

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.