Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > лишний код в стандартных библиотеках


Автор: GoldFinch 13.4.2009, 15:31
берем какую-нибудь тривиальную программу
Код

#include <cstdlib>
int main() {
    return rand()%10;
}

компилируем (msvc2008), получаем .exe размером 36Кб, размер секции кода 0x6200
а все потому что используется немалого размера mainCRTStartup, 
а данные CRT хранятся в TLS изза чего при вызове rand() используется уйма апи доступа к TLS и сохранения LastErr, а так же немало связанных с ними проверок

что с этим можно сделать?

Автор: J0ker 13.4.2009, 16:15
учитывая размер сектора любой файловой системы - не забивать себе голову глупостями
ради исключительно академического интереса - отключить CRT и юзать исключительно ОС API и асм

Автор: GoldFinch 13.4.2009, 16:32
J0ker, размер сектора почти любой файловой системы - 512 байт, размер страницы памяти - 4Кб
я хочу юзать стандартные библиотеки, но при этом чтобы небыло лишнего кода
"юзать исключительно ОС API и асм" - это совет не для раздела С++

Автор: Lazin 13.4.2009, 16:42
Цитата(GoldFinch @  13.4.2009,  15:31 Найти цитируемый пост)
что с этим можно сделать?

начиная с vs2005 - ничего, а в старых версиях студии, можно использовать signle threaded rtl
но смысла я не вижу, в более менее сложном приложении лучше использовать multithreaded версию rtl

Автор: J0ker 13.4.2009, 16:42
пардон
имелось ввиду конечно кластер

Автор: GoldFinch 13.4.2009, 17:19
Lazin, например есть задача заполнить большой массив случайными значениями, смоделировать случайный процесс, вобщем надо много раз вызвать функцию rand()
в делфи функция random выполняется за десяток инструкций процессора (могло бы быть и меньше)
Код

___:30002D9C Random          proc near
___:30002D9C                 push    ebx
___:30002D9D                 xor     ebx, ebx
___:30002D9F                 imul    edx, RandSeed[ebx], 8088405h
___:30002DA9                 inc     edx
___:30002DAA                 mov     RandSeed[ebx], edx
___:30002DB0                 mul     edx
___:30002DB2                 mov     eax, edx
___:30002DB4                 pop     ebx
___:30002DB5                 retn
___:30002DB5 Random          endp
 
а в С++ трасса rand() состоит из 80 инструкций, причем весьма не быстрых:
Код

Address  Thread   Command                                   ; Registers and comments
00401593 Main     MOV EDI,EDI
00401595 Main     PUSH ESI
00401596 Main     CALL cstd_tes.0040151A
0040151A Main     MOV EDI,EDI
0040151C Main     PUSH ESI
0040151D Main     PUSH EDI
0040151E Main     CALL DWORD PTR [<&KERNEL32.GetLastError>]
RtlGetLastWin32Er>MOV EAX,DWORD PTR FS:[18]                 ; EAX=7FFDD000
7C910337 Main     MOV EAX,DWORD PTR [EAX+34]                ; EAX=00000000
7C91033A Main     RETN
00401524 Main     PUSH DWORD PTR [40A00C]
0040152A Main     MOV EDI,EAX                               ; EDI=00000000
0040152C Main     CALL cstd_tes.004013C2
004013C2 Main     MOV EDI,EDI
004013C4 Main     PUSH ESI
004013C5 Main     PUSH DWORD PTR [40A010]                   ; TlsIndex = 1
004013CB Main     CALL DWORD PTR [<&KERNEL32.TlsGetValue>]
TlsGetValue       MOV EDI,EDI
7C809742 Main     PUSH EBP
7C809743 Main     MOV EBP,ESP                               ; EBP=0012FF4C
7C809745 Main     MOV EAX,DWORD PTR FS:[18]                 ; EAX=7FFDD000
7C80974B Main     MOV ECX,DWORD PTR [EBP+8]
7C80974E Main     CMP ECX,40
7C809751 Main     JNB kernel32.7C84495C
7C809757 Main     AND DWORD PTR [EAX+34],0
7C80975B Main     MOV EAX,DWORD PTR [EAX+ECX*4+E10]         ; EAX=7C809740
7C809762 Main     POP EBP                                   ; EBP=0012FFC0
7C809763 Main     RETN 4
004013D1 Main     MOV ESI,EAX                               ; ESI=7C809740
004013D3 Main     TEST ESI,ESI
004013D5 Main     JNZ SHORT cstd_tes.004013F2
004013F2 Main     MOV EAX,ESI
004013F4 Main     POP ESI                                   ; ESI=FFFFFFFF
004013F5 Main     RETN
00401531 Main     CALL EAX
TlsGetValue       MOV EDI,EDI
7C809742 Main     PUSH EBP
7C809743 Main     MOV EBP,ESP                               ; EBP=0012FF58
7C809745 Main     MOV EAX,DWORD PTR FS:[18]                 ; EAX=7FFDD000
7C80974B Main     MOV ECX,DWORD PTR [EBP+8]                 ; ECX=00000002
7C80974E Main     CMP ECX,40
7C809751 Main     JNB kernel32.7C84495C
7C809757 Main     AND DWORD PTR [EAX+34],0
7C80975B Main     MOV EAX,DWORD PTR [EAX+ECX*4+E10]         ; EAX=00331E90
7C809762 Main     POP EBP                                   ; EBP=0012FFC0
7C809763 Main     RETN 4
00401533 Main     MOV ESI,EAX                               ; ESI=00331E90
00401535 Main     TEST ESI,ESI
00401537 Main     JNZ SHORT cstd_tes.00401587
00401587 Main     PUSH EDI                                  ; Error = ERROR_SUCCESS
00401588 Main     CALL DWORD PTR [<&KERNEL32.SetLastError>]
RtlSetLastWin32Er>MOV EDI,EDI
7C910342 Main     PUSH EBP
7C910343 Main     MOV EBP,ESP                               ; EBP=0012FF58
7C910345 Main     MOV EAX,DWORD PTR FS:[18]                 ; EAX=7FFDD000
7C91034B Main     MOV ECX,DWORD PTR [EBP+8]                 ; ECX=00000000
7C91034E Main     MOV DWORD PTR [EAX+34],ECX
7C910351 Main     POP EBP                                   ; EBP=0012FFC0
7C910352 Main     RETN 4
0040158E Main     POP EDI                                   ; EDI=7C910738
0040158F Main     MOV EAX,ESI                               ; EAX=00331E90
00401591 Main     POP ESI                                   ; ESI=FFFFFFFF
00401592 Main     RETN
0040159B Main     MOV ESI,EAX                               ; ESI=00331E90
0040159D Main     TEST ESI,ESI
0040159F Main     JNZ SHORT cstd_tes.004015A9
004015A9 Main     MOV EAX,ESI
004015AB Main     POP ESI                                   ; ESI=FFFFFFFF
004015AC Main     RETN
00401024 Main     MOV ECX,DWORD PTR [EAX+14]                ; ECX=00000001
00401027 Main     IMUL ECX,ECX,343FD                        ; ECX=000343FD
0040102D Main     ADD ECX,269EC3                            ; ECX=0029E2C0
00401033 Main     MOV DWORD PTR [EAX+14],ECX
00401036 Main     MOV EAX,ECX                               ; EAX=0029E2C0
00401038 Main     SHR EAX,10                                ; EAX=00000029
0040103B Main     AND EAX,7FFF
00401040 Main     RETN


Автор: J0ker 13.4.2009, 18:12
GoldFinch,
случайные числа вообще тема сложная
здесь наряду со скоростью надо рассматривать распределение и "случайность"

Автор: GoldFinch 13.4.2009, 18:52
J0ker, ты читал о чем я пишу? алгоритм формирования случайного числа и в С++ и в паскале и наверное во многих других ЯП один и тот же: randseed=randseed*a+b
но в С++ в функции rand() много лишнего кода никак не связанного с генерацией случайного числа

Автор: Любитель 13.4.2009, 19:36
GoldFinch, вроде ж уже выяснили - многопоточный рантайм, проблемы синхронизации (чтобы в двух потоках не было одинаковой последовательности твоих чисел).

Автор: GoldFinch 13.4.2009, 19:50
Цитата(Любитель @  13.4.2009,  20:36 Найти цитируемый пост)
чтобы в двух потоках не было одинаковой последовательности твоих чисел

это как это будут одинаковые последоватльности в двух потоках если числа случайные берутся из одного ГПСЧ?
вот как раз когда у каждого потока свой ГПСЧ, то и могут возникнуть одинаковые последовательности

Автор: J0ker 13.4.2009, 20:07
GoldFinch, я подозреваю (не вчитывался в код) что в VC rand реализован per-thread - в дельфи во-первых соершенно не thread-safe, а во-вторых с т.з. секьюрити не per-thread rand - это явный косяк

Автор: Cтpaнник 13.4.2009, 20:45
Да можешь уже и не подозревать, - так и есть, в VC++ rand() действительно per-thread. По крайней мере, в VC++ 2005 я этим вопросом интересовался.

Автор: GoldFinch 13.4.2009, 20:47
J0ker, Cтpaнник, вы посты читаете или сразу пишете? =\
Цитата(GoldFinch @  13.4.2009,  16:31 Найти цитируемый пост)
данные CRT хранятся в TLS изза чего при вызове rand() используется уйма апи доступа к TLS


Автор: vinter 13.4.2009, 20:54
GoldFinch, дык в чем вопрос то? утебя есть ответ, что тебя еще интересует? Не нравятся студийные накладки - не используй ее. Благо есть бесплатные аналоги.

Автор: azesmcar 13.4.2009, 20:55
Я не совсем понимаю в чем вопрос?
CRT непотокобезопасная библиотека, она использует глобальные переменные итд...чтобы решить эту проблему ее загружают в TLS (Thread Local Storage). Если вопрос

Цитата(GoldFinch @  13.4.2009,  15:31 Найти цитируемый пост)
что с этим можно сделать?

то вот ответ

Цитата(Lazin @  13.4.2009,  16:42 Найти цитируемый пост)

начиная с vs2005 - ничего, а в старых версиях студии, можно использовать signle threaded rtl
но смысла я не вижу, в более менее сложном приложении лучше использовать multithreaded версию rtl

либо используй Single Thread, либо забудь об этом.

Добавлено через 1 минуту и 11 секунд
опередили smile 

Автор: Rififi 13.4.2009, 21:55
GoldFinch, 
что с этим можно сделать?
писать всё на ассемблере, как настоящий джедай, а не чайник какойта, а с++ - фтопку.

Автор: GoldFinch 13.4.2009, 23:38
лишние проверки STL отключаются дефайном "#define _SECURE_SCL 0"
может в CRT тоже есть чтото подобное?

или может гдето есть оптимизированная версия CRT?

Автор: J0ker 14.4.2009, 01:20
GoldFinch, ты джедай или где? теж сказали - на ассемблере  smile 

Автор: azesmcar 14.4.2009, 08:30
GoldFinch
Не видел отдельного CRT. А если попробовать GCC?

Автор: GoldFinch 14.4.2009, 08:42
azesmcar, нехочу gcc, в msvc слишком много вкусных вещей которых нет в gcc
одно наличие __asm чего стоит

Автор: azesmcar 14.4.2009, 08:54
GoldFinch
не понял?? кто сказал что в GCC нет ассемблерных вставок?
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
Практически все что есть в Визуал студии заменяется аналогами в GCC. Надо только поискать.

Автор: GoldFinch 14.4.2009, 09:41
azesmcar, я не сказал что их нет, я говорю что синтаксис асм вставок в msvc удобнее чем в gcc
может все что есть в Визуал студии и заменяется аналогами в GCC, но не факт что эта замена так же хороша как и оригинал

Автор: azesmcar 14.4.2009, 09:51
Цитата

много вкусных вещей которых нет в gcc
одно наличие __asm чего стоит 

а это кто говорил?

Цитата

может все что есть в Визуал студии и заменяется аналогами в GCC, но не факт что эта замена так же хороша как и оригинал 

спорный вопрос что считать оригиналом и что лучше. С тем же успехом скажу - не факт что микрософтовские функции лучше POSIX.

Автор: J0ker 14.4.2009, 16:32
...............

Автор: 586 14.4.2009, 16:51
Код
#pragma comment (linker, "/entry:main /opt:nowin98")     // for visual c++

#include <cstdlib>
int main() {
    return rand()%10;  // используете Run-Time Library на свой страх и риск, т.к. он не инициализирован
}

Автор: GoldFinch 14.4.2009, 17:53
586, этот код не работает, какой смысл постить неработающий код?

Автор: Alca 14.4.2009, 18:23
Цитата

586, этот код не работает, какой смысл постить неработающий код?

Кажись это для шестерки.

Добавлено через 1 минуту и 46 секунд
http://forum.sources.ru/index.php?showtopic=139119&view=showall

Добавлено через 3 минуты и 3 секунды
http://forum.sources.ru/index.php?act=Attach&type=post&id=1069983

Автор: 586 15.4.2009, 00:28
Цитата(Alca @  14.4.2009,  19:23 Найти цитируемый пост)
Кажись это для шестерки.

В любой студии должно работать. В 98 и 2005 точно.
Цитата(GoldFinch @  14.4.2009,  18:53 Найти цитируемый пост)
тот код не работает, какой смысл постить неработающий код? 

Что именно не работает? Какая ошибка?

Автор: GoldFinch 15.4.2009, 08:19
586, в msvc2008 валится после ntdll.RtlDecodePointer, видимо потому что не был выполнен EncodePointer

Автор: zim22 15.4.2009, 08:30
Цитата(GoldFinch @  14.4.2009,  17:53 Найти цитируемый пост)
этот код не работает, какой смысл постить неработающий код?

у меня работает. MSVC 2008 Professional.
только при сборке Release предупреждает: warning LNK4229: invalid directive '/opt:nowin98' encountered; ignored
размер debug версии exe-шника: 20480 байт
размер release: 3584 байт

Автор: 586 15.4.2009, 14:46
Цитата(GoldFinch @  15.4.2009,  09:19 Найти цитируемый пост)
в msvc2008 валится после ntdll.RtlDecodePointer, видимо потому что не был выполнен EncodePointer 

У тебя Debug-версия? Это нужно делать в Release-версии.
Что отображено в окне Call Stack? Debug->Windows->Call Stack. Эта информация может прояснить ситуацию.

Цитата(zim22 @  15.4.2009,  09:30 Найти цитируемый пост)
только при сборке Release предупреждает: warning LNK4229: invalid directive '/opt:nowin98' encountered; ignored

/opt:nowin98 - устаревшая опция. В 2005 студии (и старше) эта опция вшита в линкер по умолчанию.

Автор: GoldFinch 15.4.2009, 15:23
zim22, у тебя CRT в dll, естественно все работает
586, компилю релиз со статическим CRT, дебажу олькой, где и как валится прога я уже писал, 
прога выполняет DecodePointer и call eax, указатель битый, прога прыгает вникуда и валится

Автор: 586 15.4.2009, 15:39
Цитата(GoldFinch @  15.4.2009,  16:23 Найти цитируемый пост)
у тебя CRT в dll, естественно все работает

Правильно. И рантайм инициализируется частично в DllMain DLL_PROCESS_ATTACH.

А статический рантайм будет некорректно работать, потому что он не инициализирован.

Автор: GoldFinch 15.4.2009, 16:37
586, и как использование длл с CRT помогает решить сабжевую проблему?

(длл с CRT сама по себе - зло, с ней программы даже не компе с msvc не работают о_О)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)