Проблема компиляции в VS 2005

Тема в разделе "LANGS.C", создана пользователем Asterix, 20 окт 2006.

  1. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Проблема компиляции в VS 2005

    такой код:
    Код (Text):
    1. void _test(void* dest, unsigned long len)
    2. {
    3.     while (len--)
    4.     {
    5.         *(char *)dest = '\0';
    6.         dest = (char *)dest + 1;
    7.     }
    8. }
    9.  
    10.  
    11.  
    12. int CheckOS()
    13. {
    14.     OSVERSIONINFO osvi;
    15.  
    16.     _test(&osvi, sizeof(OSVERSIONINFO));
    17.     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    18.     if ( GetVersionEx(&osvi) )
    19.         return osvi.dwPlatformId == VER_PLATFORM_WIN32_NT;
    20.     return 0;
    21. }
    в опциях проекта установлен ключ линкеру /NODEFAULTLIB
    но линкер ругается
    error LNK2001: unresolved external symbol _memset

    Как заставить компилятор забыть про crt совсем и не быть
    таким умным заменяя мою функцию на memset

    Код (Text):
    1. PUBLIC  ?_test@@YAXPAXK@Z               ; _test
    2. EXTRN   _memset:PROC
    3. ; Function compile flags: /Ogtpy
    4. ;   COMDAT ?_test@@YAXPAXK@Z
    5. _TEXT   SEGMENT
    6. ?_test@@YAXPAXK@Z PROC                  ; _test, COMDAT
    7. ; _dest$ = eax
    8. ; Line 124
    9.     push    148                 ; 00000094H
    10.     push    0
    11.     push    eax
    12.     call    _memset
    13.     add esp, 12                 ; 0000000cH
    14. ; Line 127
    15.     ret 0
    16. ?_test@@YAXPAXK@Z ENDP                  ; _test
    компилируется с ключами
    Код (Text):
    1. /O2 /Ob2 /GL /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_WINDLL" /FD /EHsc /MT /Zp1 /GS- /J /FA /Fa"Release\\" /Fo"Release\\" /Fd"Release\vc80.pdb" /W3 /nologo /c /Zi /TP /errorReport:prompt
     
  2. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Asterix
    Добавь /Oi, чтоб заинлайнить memset
     
  3. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    вот в мсдн написано
    Код (Text):
    1. Option                       Equivalent to                     Comment  
    2. /O1 (Minimize Size)       /Og /Os /Oy /Ob2 /Gs /GF /Gy        Creates the smallest code in the majority of cases.
    3.  
    4. /O2 (Maximize Speed)      /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy    Creates the fastest code in the majority of cases. (default setting for release builds)
     
  4. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    это при том что саму CheckOS() компилятор инлайнит
     
  5. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Тут описан такой баг, но для 64 бит. А что, если юзать memset() вместо _test()?
     
  6. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Quantum
    это уже танцы с бубном, хотелось бы прямые пути для начала попробовать =)
     
  7. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    изначально я вобще хотел использовать
    OSVERSIONINFO osvi = {0};
    и компилятор 6-й студии заменил бы этот код циклом, а вот 2005 сильно умный
     
  8. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Quantum
    Так это именно баг? Странный какой-то баг, в чём проблема с встраиванием таких примитивов? В их агрессивной оптимизации? Ну ладно, не может memset заинлайнить. Но вот чтоб думать за разработчика, заменяя его код вызовами существующих функций библиотеки — это уж черезчур. 7.1 такой фигнёй не страдает.
     
  9. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    А по каким признакам компилятор догадывается, что _test - это аналог memset?
    Может сделать другой алгоритм обнуления, чтобы сбить с толку компилятор?
     
  10. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    cresta
    Предлагаешь исполнить с ним танго? :))
     
  11. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    IceStudent

    Не танго танцевать, а по рукам дать ему. Поэтому и нужно определить, откуда у него эти руки растут :)
     
  12. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Asterix
    Мне просто интересно. Может, эта эвристика с memset выполняется компилятором после препроцессора intrinsic'ов и инлайнов. Поэтому /Oi не работает.

    IceStudent
    В MS это называют особенностью, хотя я лично не могу понять, почему они связывают это с x64 и дровами режима ядра.
     
  13. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    это не Каспер чтобы пытаться спрятать от компилятора узнаваемый им код
    путем манипуляций с кодом, понятно что код можно переписать, но это танцы с бубном,
    в идеале желательно повлиять на компилятор с помощью ключей компиляции
     
  14. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Может быть это встроенная и неотключаемая ключами "фишка"?
    Вполне в духе МС: чтобы не лезли на уровень ниже crt.
     
  15. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Quantum
    если ты про переименование то это проблему не решает, т.е. ничего не изменилось
     
  16. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    такой код тоже не катит
    Код (Text):
    1. void _test(void* dest, unsigned long len)
    2. {
    3.     for (unsigned long i = 0; i < len; i++)
    4.     {
    5.         *((char *)dest + i) = '\0';
    6.     }
    7. }
     
  17. PE386

    PE386 New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    127
    Код (Text):
    1. void _test(void* dest, unsigned long len)
    2. {
    3.     for (unsigned long i = 0; i < len; i++)
    4.     {
    5.         *((char *)dest + i) &= '\0';
    6.     }
    7. }
    А так пробовал?
     
  18. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    PE386
    попробовал - эффект тот же
     
  19. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Наверняка компилятор реагирует на константу (0). И считает что тут нужен memset.
    А если поксорить каждый байт сам на себя? Явной константы нет. Или вычесть самого из себя.

    *((char *)dest + i) = *((char *)dest + i) ^ *((char *)dest + i);
     
  20. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Asterix
    Нет, я бы вообще убрал test и использовал memset.