LINUX.ORG.RU

При обращении по указателю программа падает

 ,


0

1

Программа работает с буфером готовых данных char*. Используется две структуры:

struct Buffer
{
  uint32_t bufsize;
  Bufdata* data;
}

struct Bufdata
{
  uint32_t datasize;
  const uint32_t* data;
}

Код:

Buffer* buf = (Buffer*)rawDataAsCharArray;
Bufdata* bdata = buf->data;
printf(bdata->datasize); //упс, упало
Если в Buffer убрать поле Bufdata* data и сделать так, то все норм:
Bufdata* bdata = (Bufdata*)(rawDataAsCharArray+sizeof(Buffer) );
printf(bdata->datasize); //ок
Компилятор - GCC 5.3.0 Чядн?



Последнее исправление: cetjs2 (всего исправлений: 2)

Вангую ошибку сериализации/десериализации, а именно неучитывание выравнивания полей структуры.

unC0Rr ★★★★★
()

Мда. Этот rawDataAsCharArray откуда берётся? Ты, наверное, обращаешься по рандомно сгенерированному адресу с закономерным результатом.

anon8
()

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

И если ты думаешь что struct Buffer это размер + данные произвольного размера, то нет, это не так. Такое делают обычно как-то так:

struct Buffer
{
  uint32_t bufsize;
  char data[1];
}

struct Bufdata
{
  uint32_t datasize;
  const uint32_t data[1];
}

struct Buffer* buf = (struct Buffer*)rawDataAsCharArray;
struct Bufdata* bdata = (struct Bufdata*)buf->data;
printf(bdata->datasize);
slovazap ★★★★★
()

В Bufdata* data попадают rawDataAsCharArray[4 - 7] (если нет выравнивания в структуре) элементы. Вряд ли там валидный указатель на Bufdata

undef ★★
()
printf(bdata->datasize); //упс, упало

Странный какой-то printf, может надо что-то типа:

printf("%" PRIu32 "\n", bdata->datasize);
Если проблема не в этом, покажи минимальный пример где у тебя что-то там падает.

Тут например https://wandbox.org/permlink/YTpGR5JohkyshHzU работает

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

Вообще-то да, это UB https://stackoverflow.com/a/48100169

но обычно это работает. Каст через union (как в Си) делать нельзя - в крестах это тоже UB. Можно через memcpy копировать указатель, если выравнивание там правильное.

Еще есть расширение __attribute__((__may_alias__)) https://gcc.gnu.org/onlinedocs/gcc-5.3.0/gcc/Type-Attributes.html

SZT ★★★★★
()
Последнее исправление: SZT (всего исправлений: 1)

Чядн?

Краткий ответ - всё.

Начнем с конца (тм)

....
printf(bdata->datasize);
1. datasize - кто, где, когда и при каких обстоятельствах пишет туда значение? Если перед нами весь код - туда не пишет никто и никогда.
2. первый аргумент функции printf - строка, а вовсе не uint32_t.

в предыдущих сериях

Buffer* buf = (Buffer*)rawDataAsCharArray;
то, что мы делаем в этой строке выглядит примерно так
uint32 | align | ptr | align  
^^^^^^^?????
char* //"F*ck that f*king memory block"
Что теперь лежит в ptr? ХЗ. Что угодно.

olelookoe ★★★
()
Ответ на: комментарий от SZT

А, еще __attribute__ ((aligned (1))) тоже может пригодиться, если переводить указатель без правильного выравнивания в указатель на структуру

SZT ★★★★★
()
Ответ на: комментарий от olelookoe

1. Пишет туда fstream, один раз.

2. printf("%d", bdata->datasize), выхлоп нужен для проверки что работает, прога 32 бита онли.

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

Про связь указателей и массивов давно прочитал. Результат в первом посте.

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