Анатомия C Run-Time, или Как сделать программу немного меньшего размера
Страница 12. Использование Standard Template Library


 

Использование Standard Template Library

А как же насчет Standard Template Library (STL)? Насколько она завязана на CRT, можно ли использовать её в сверхмалых проектах?

Реализация STL от Dinkumware, поставляемая вместе с VC 5.0 и 6.0, доступна в исходных файлах, так что проблем с компоновкой не возникает. В крайнем случае, всегда можно исправить исходники или сделать какую-нибудь заглушку на #define'ах (перебивающую имена конструкций, тянущих за собой CRT). Другая проблема - в том, что STL повсеместно использует операторы динамического выделения памяти. Как уже говорилось, это вызывает необходимость собственной реализации операторов new/delete. Это можно сделать, например, так (идея позаимствована из atlimpl.cpp):

// stub.cpp - the "mini-CRT" implementation file

void* __cdecl malloc(size_t n)
{
void* pv = HeapAlloc(GetProcessHeap(), 0, n);
return pv;
}
void* __cdecl calloc(size_t n, size_t s)
{
return malloc(n*s);
}
void* __cdecl realloc(void* p, size_t n)
{
if (p == NULL) return malloc(n);
return HeapReAlloc(GetProcessHeap(), 0, p, n);
}
void __cdecl free(void* p)
{
if (p == NULL) return;
HeapFree(GetProcessHeap(), 0, p);
}
void* __cdecl operator new(size_t n)
{
return malloc(n);
}
void __cdecl operator delete(void* p)
{
free(p);
}

 

Вот пример программы, которая будет спокойно собрана с помощью такого подхода без стартового кода CRT:

#include <windows.h>
#include "stub.cpp"
#include <map>

typedef std::map<int, int> IntMap;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd )
{
IntMap m;
for (int j=0; j<100; j++) m[j*j]=j;
IntMap::iterator i=m.find(49);
MessageBox(0, (i==m.end())?"49 was not found":"49 was found",
"std::map test", MB_OK);
return 0;
}

Для сборки этого примера необходимо использовать следующую командную строку:

cl test.cpp user32.lib kernel32.lib /link /nod /opt:nowin98 /subsystem:windows /entry:WinMain

Библиотека импорта kernel32.lib необходима для функций работы с Win32-кучей.

Что касается других реализаций STL, предоставлю слово Павлу Блудову:

"Страшная тайна STL от SGI и HP в том, что им совершенно не нужна CRT.

С двумя оговорками:

  1. Не используется C++ Exception Handling
  2. (Вытекает из первой) определен макрос __THROW_BAD_ALLOC, например, так:
#ifndef _CPPUNWIND 
#define __THROW_BAD_ALLOC \
::MessageBox(NULL, _T("STL: Out of memory."), NULL, MB_OK | MB_ICONSTOP); \
::ExitProcess(-5);
#endif _CPPUNWIND
#include <stl_config.h>

если посмотреть на __THROW_BAD_ALLOC, то он являет собой

#define __THROW_BAD_ALLOC fprintf(stderr, "out of memory\n"); exit(1) 

именно эта строчка, и никакая другая, нуждается в CRT. Ну, если быть совсем точным, std::string'у может понадобиться CRT. Тут уж ничего не попишешь. Используйте WTL::CString.

Павел."

Слова о std::string в полной мере справедливы и для реализации STL от Dinkumware. Если вы ищете реализацию полноценного строкового класса, не использующего стартовый код CRT, советую взглянуть на CascString в составе библиотеки ascLib.

 
« Предыдущая статья   Следующая статья »