[sisyphus] Странности при переходе объединении двух целых в вещественное на x86_64

Roman Savochenko rom_as на diyaorg.dp.ua
Пт Авг 7 09:49:26 MSD 2009


Kirill A. Shutemov wrote:
>> Имеется некая целевая задачка собрать из двух 16-разрядных целых
>> вещественное (float), 32 разряда.
>> Казалось-бы тривиальная задача, которая решается кодом типа
>> int w1 = 62915, w2 = 16456;
>> ui32 vl = ((w2&0xffff)<<16) | w1&0xffff;
>> //sleep(1);
>> printf("TEST 00: %f\n",*(float*)&vl);
>>
>> И как ожидалось на x86_32 он работает корректно при различной нагрузке.
>> А вот на x86_64 замечается ситуация когда вместо 3.14 получаем ноль.
>> Причём в тестовой программке с единственным потоком всё работает нормально,
>> а на высоконагруженном процессе с десятками потоков, из которых около пяти
>> работают с периодом 5мс. устойчиво получатся 0.
>> Если раскомментирую sleep, то получаю номальный результат 3.14.
>>
>> Кто нибуть может такое поведение объяснить?
>>     
> Похоже, вы нарушили strict aliasing. Попробуйте собрать с -Wstrict-aliasing=2.
> Если будет ругаться, то это наверно оно(см. оговорку в мане насчёт этой опции).
>
> Нарушение strict aliasing может сломать некоторые оптимизации. Два выхода --
> или собрать с -fno-strict-aliasing или переписать код корректней.
>   
Я его записывал уже тремя различными способами с одинаковым результатом. :)

int w1 = 62915, w2 = 16456;
float vl = 0;
*(ui16*)&vl = w1;
*(((ui16*)&vl)+1) = w2;
printf("TEST 00: %f\n",vl);

и

int w1 = 62915, w2 = 16456;
char vl[4];
*(ui16*)vl = w1;
*(((ui16*)vl)+1) = w2;
printf("TEST 00: %f\n",*(float*)vl);

С уважением, Роман
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя     : rom_as.vcf
Тип     : text/x-vcard
Размер  : 218 байтов
Описание: отсутствует
Url     : <http://lists.altlinux.org/pipermail/sisyphus/attachments/20090807/66140fb2/attachment.vcf>


Подробная информация о списке рассылки Sisyphus