Показаны сообщения с ярлыком ub. Показать все сообщения
Показаны сообщения с ярлыком ub. Показать все сообщения

2013-01-24

сишники узнали о for_each

Из одной библиотеки (на которую я уже жаловался)

typedef void (* clist_func)(void *, void *);
void clist_foreach(clist * lst, clist_func func, void * data) {
  clistiter * cur;
  for(cur = clist_begin(lst) ; cur != NULL ; cur = cur->next)
    func(cur->data, data);
}

//....

clist_foreach(list, (clist_func)free, NULL);

Если кто забыл -- void free(void*). То есть, имеем UB по стандарту С. Да, оно работает, пока cdecl и компилятор не намудрит с оптимизацией.

Интересный факт: так как это UB, компилятор имеет право делать все, что угодно. Prerelease GCC 4.3, если типы функций были несовместимы, возвращал NULL. К релизу пришлось поменять назад, ибо дофига софта "поломалось".

2012-02-23

"оптимизаторы", блин

Прочитал цитату на ITHappends
Смотрю код высоконагруженного сервера. В ядре обсчёта вижу код типа:

func() {
ObjectGame* OG=MainOG;
while(OG->next!=NULL)
{
ia=(int*)OG+12;
i=*ia;
/* что-то делает*/
*ia=i;
/* код функции, внутри функции ia претерпевает различные изменения*/
OG=OG->next;
}
}


С большими глазами иду к прогеру, который это всё написал. Спрашиваю: почему он не пользуется методами Set и Get, и вообще, почему именно 12 байт?

На что он мне отвечает: «Внутри кода функции есть ветвящийся цикл, в котором перебираются многие параметры объекта. Если пользоваться методами Set и Get, а это переход по адресу, причём у каждого объекта он свой, конвейер процессора офигеет и сбросится. Это плюс 30 тактов на каждый переход. Всего таких объектов в секунду надо обсчитать порядка нескольких миллионов. Частота ядра — три миллиарда операций в секунду. Отсюда вывод: идите вы лесом со своим ООП!»

Меня аж передернуло.

>> ia=(int*)OG+12;
а потом этот код скомпилировали другим компилятором, на другой платформе, под другую архитектуру или с другими настройками(тут даже переключение debug/release может выстрелить). И happy debugging готов. Функция продолжает считать быстро, но выдает ошибочный результат.

>>  Если пользоваться методами Set и Get, а это переход по адресу, причём у каждого объекта он свой,
Лолчто?

Отсюда вывод: гнать нахер таких "оптимизаторов" из професии.


2011-09-08

ненавижу C style cast

Нарвался на эпичную багу с C style cast.
Был старый код:

CTreeCtrl * pTree = (CTreeCtrl *)&m_Tree;
...
... pTree->GetChildItem(TVI_ROOT) ...

Зачем там вообще приведение типа -- я хз, эта функция была писан не мной.

В один прекрасный момент тип m_Tree меняется из наследника CTreeCtrl в std::auto_ptr<CTreeCtrl>.

И вместо static_cast мы имеем уже reinterpret_cast.
И ни единого ворнинга от компилятора по этому поводу.