Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> typecasting 
:(
    Опции темы
ubique
Дата 31.8.2010, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 5.8.2008

Репутация: нет
Всего: нет



Работаю с BPF под FreeBSD, примерно так:

Код

struct bpf_hdr *buf;
ssize_t size;
size = read(iface->fd, buf, iface->buflen);
frame = (struct ether_header *) buf + buf->bh_hdrlen;


В случае, когда buf + buf->hdr_len typecast'тся как char *, т.е.
Код

frame = (char *) buf + buf->hdr_len

все отлично.
В случае, же
Код

frame = (struct ether_header *) buf + buf->bh_hdrlen;

элементы frame содержат ерунду.
Возникает два вопроса:

1. От чего такое происходит?
2. Как с этим _правильно_ бороться, ибо если использовать typecast к (char *), то компилятор (gcc, clang) выдает примерно следущее:
Код

../os/raw_packet_freebsd.c:118:11: warning: incompatible pointer types assigning 'char *', expected 'struct ether_header *'
      [-pedantic]
    frame = (char *) buf + buf->bh_hdrlen;
          ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


PM MAIL   Вверх
ИванМ
Дата 31.8.2010, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

Репутация: 3
Всего: 23



Цитата(ubique @  31.8.2010,  16:09 Найти цитируемый пост)
От чего такое происходит?

От того что char и ether_header имеют разный размер и соответственно при сдвиге указателя происходит перемещение на разную длину.
Используйте смело приведение к char* - в компиляторе всего лишь предупреждение, а не ошибка. Можно это предупреждение отключить в настройках.

Это сообщение отредактировал(а) ИванМ - 31.8.2010, 16:15
PM MAIL   Вверх
mes
Дата 31.8.2010, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(ubique @  31.8.2010,  15:09 Найти цитируемый пост)
 buf->hdr_len

какого типа ? а дальше арифметика указателей smile



--------------------
PM MAIL WWW   Вверх
ubique
Дата 31.8.2010, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 5.8.2008

Репутация: нет
Всего: нет



Цитата(ИванМ @  31.8.2010,  16:14 Найти цитируемый пост)
От того что char и ether_header имеют разный размер и соответственно при сдвиге указателя происходит перемещение на разную длину.
Используйте смело приведение к char* - в компиляторе всего лишь предупреждение, а не ошибка. Можно это предупреждение отключить в настройках.


А разве указатели на struct ether_header и char имеют различную длину? Размер указателя же определяется архитектурой процессора (4 байта для 32, и 8 для 64). У меня же typecast происходит не в статические данные, а в указатель. То есть, я понимаю, почему отличается такое поведение:
Код

frame = (char *) ...

и
Код

frame = (struct ether_header *)

А вот почему результат typecast'инг к указателем на разные обьекты отличается - не понимаю.

Добавлено через 1 минуту и 23 секунды
Цитата(mes @  31.8.2010,  16:16 Найти цитируемый пост)
какого типа ? а дальше арифметика указателей

int.
Я понимаю арифметику указателей. buf + buf->hdrlen в независимости от typecast'инга будет указывать на один и тот же байт в памяти.
Результат зависит от того типа, к указателю которого я привожу этот адрес. Это не понятно.
PM MAIL   Вверх
ИванМ
Дата 31.8.2010, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

Репутация: 3
Всего: 23



Цитата(ubique @  31.8.2010,  16:20 Найти цитируемый пост)
А разве указатели на struct ether_header и char имеют различную длину?

Указатели имеют одинаковую длину, но смещение определяется не размером указателя, а размером данных, на которые этот указатель ссылается.
PM MAIL   Вверх
ubique
Дата 31.8.2010, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 5.8.2008

Репутация: нет
Всего: нет



Цитата(ИванМ @  31.8.2010,  16:22 Найти цитируемый пост)
Указатели имеют одинаковую длину, но смещение определяется не размером указателя, а размером данных, на которые этот указатель ссылается. 

Те, фактически получается так:
Код

frame = buf + buf->hdrlen * sizeof(char)

в первом случае, а во втором:
Код

frame = buf + buf->hdrlen * sizeof(struct ether_header)


Если так, то все понятно.
PM MAIL   Вверх
djamshud
Дата 31.8.2010, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 4
Всего: 39



Имейте в виду, что если buf+something попадет в невыровненную область на некотороых архитектурах (например ARM) получите ooops.


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
ИванМ
Дата 31.8.2010, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1260
Регистрация: 19.6.2006
Где: СПб

Репутация: 3
Всего: 23



Цитата(ubique @  31.8.2010,  16:25 Найти цитируемый пост)
Те, фактически получается так

Совершенно верно
PM MAIL   Вверх
djamshud
Дата 31.8.2010, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 4
Всего: 39



То есть ошибку доступа к памяти. Безопасно и переносимо - делать memcpy между кучей-малой и объектом структуры.


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
ubique
Дата 31.8.2010, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 5.8.2008

Репутация: нет
Всего: нет



Цитата(ИванМ @  31.8.2010,  16:26 Найти цитируемый пост)
Совершенно верно 

Спасибо.

Цитата(djamshud @  31.8.2010,  16:26 Найти цитируемый пост)
Имейте в виду, что если buf+something попадет в невыровненную область на некотороых архитектурах (например ARM) получите ooops. 

А что можно почитать про выравнивание, что стало понятней что это?
Спасибо.
PM MAIL   Вверх
djamshud
Дата 31.8.2010, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 4
Всего: 39



http://ru.wikipedia.org/wiki/Выравнивание данных

Начать отсюда, а дальше в гугл. Литературу не подскажу.


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
ubique
Дата 31.8.2010, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 5.8.2008

Репутация: нет
Всего: нет



Цитата(djamshud @  31.8.2010,  16:35 Найти цитируемый пост)
http://ru.wikipedia.org/wiki/Выравнивание данных

Начать отсюда, а дальше в гугл. Литературу не подскажу.


Спасибо.
PM MAIL   Вверх
Леопольд
Дата 31.8.2010, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 3
Всего: 13



Цитата(djamshud @  31.8.2010,  16:26 Найти цитируемый пост)
Имейте в виду, что если buf+something попадет в невыровненную область на некотороых архитектурах (например ARM) получите ooops. 
На Санах в Солярке получаем "bus error", вроде...



--------------------
вопросов больше чем ответов
PM MAIL   Вверх
djamshud
Дата 31.8.2010, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 4
Всего: 39



Леопольд, это еи есть ошибка доступа к памяти. Даже на x86 такие "приемы" иногда приводят к существенному подвисанию.

Добавлено через 6 минут и 20 секунд
В обшем, если не хотите заниматься поиском неуловимых багов, лучше приучить себя так не делать:).


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1207 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.