Click here to Skip to main content
Click here to Skip to main content

Tiny C Runtime Library

By , 25 Mar 2007
 

Introduction

Updated 2007-03-25: See end of article for details.

Ever designed a simple utility program, such as a hex-dump program, only to find your simple program is a full 64K, optimized for size, when all it does is read a file and print to stdout? Ever wonder what happened to those good ol' DOS days where programs had to be small? Where a COM file was limited to 64K? Or when you can write a bare-bones DOS-style protected mode operating system kernel in about 64K?

Well look no further. Here I will examine what causes this code bloat, and what can be done to fix it.

Background

Matt Pietrek wrote an excellent article in the January 2001 MSDN Magazine titled Under the Hood: Reduce EXE and DLL Size with LIBCTINY.LIB. While most of this information remains valid today, I have updated some of his code to work better with Visual Studio 2005. I have also added support for functions that were not included in his article.

Intended Audience

This article is aimed at programmers who like to have control over every little detail. It is also geared towards small portable utility-like programs, where a DLL CRT is undesirable because of the need for a second file and installation program, and where the overhead of a statically linked CRT is much greater than the core program code.

Of course, by replacing the CRT, programs that rely on specifics of the Microsoft CRT will fail. For instance, if you go digging into the FILE structure, or expect a certain header on your memory allocations, or rely on the buffering features of stdio, or use locales, runtime checks, or C++ exception handling, you can't use this library. This library is aimed for use by small, simple programs, such as a hex-dump command line program or the many UNIX-style tools like cat or grep.

Many C/C++ purists will take offence at my suggestions, because the C runtime is, to them, something that shouldn't be tampered with. But bear with me, because although you might never use any of this article's information, it should at least give you an insight into how your program works.

Where's Bloat-o?

(really bad pun, I know...)

The source of this 'code bloat' is very easy to find by looking at a linker-generated map file. Here is a snippet from the demo programs' map file:

 0001:00000000       ?DumpFile@@YAXPAD@Z        00401000 f   hd.obj
 0001:00000152       _main                      00401152 f   hd.obj
 0001:0000021b       _feof                      0040121b f   LIBCMT:feoferr.obj
 0001:0000024a       _fgetc                     0040124a f   LIBCMT:fgetc.obj
 0001:00000381       _printf                    00401381 f   LIBCMT:printf.obj
 0001:00000430       __get_printf_count_output  00401430 f   LIBCMT:printf.obj
 0001:00000446       __fsopen                   00401446 f   LIBCMT:fopen.obj
 0001:0000050a       _fopen                     0040150a f   LIBCMT:fopen.obj
 0001:00000520       _memset                    00401520 f   LIBCMT:memset.obj
 0001:0000059a       __fclose_nolock            0040159a f   LIBCMT:fclose.obj
 0001:0000060d       _fclose                    0040160d f   LIBCMT:fclose.obj
 0001:00000689       __amsg_exit                00401689 f   LIBCMT:crt0dat.obj
 0001:000006ad       ___crtCorExitProcess       004016ad f   LIBCMT:crt0dat.obj
 0001:000006d3       ___crtExitProcess          004016d3 f   LIBCMT:crt0dat.obj
 ...
 0001:0000a590       __allmul                   0040b590 f   LIBCMT:llmul.obj
 0001:0000a5e0       _strchr                    0040b5e0 f   LIBCMT:strchr.obj
 0001:0000a5e6       ___from_strstr_to_strchr   0040b5e6     LIBCMT:strchr.obj

As you can see, it includes "two" functions from my program, and over "two hundred" functions in the C Runtime (CRT).

Notice that one of the functions is even ___crtCorExitProcess, a function that is used by a C++/CLI program! Other gems include multithreading support, locales, and exception handling - none of which are used by my program!

And this is with Eliminate Unreferenced Data and COMDAT Folding on!

Where do I begin?

I will first highlight the various tasks performed by the C Runtime to give the reader a better understanding of the 'magic' that happens in C and C++.

Let's start by configuring the linker to Ignore Default Libraries. Compile. I was greeted with this:

hd.obj : error LNK2001: unresolved external symbol _feof
hd.obj : error LNK2001: unresolved external symbol _fgetc
hd.obj : error LNK2001: unresolved external symbol _printf
hd.obj : error LNK2001: unresolved external symbol _fopen
hd.obj : error LNK2001: unresolved external symbol _memset
hd.obj : error LNK2001: unresolved external symbol _stricmp
hd.obj : error LNK2001: unresolved external symbol _fclose
hd.obj : error LNK2001: unresolved external symbol _exit
LINK : error LNK2001: unresolved external symbol _mainCRTStartup

Not good. Not good at all.

mainCRTStartup

Where does your console program start? Did I hear you say main? If you did, you said what I would have said before journeying into the inner Stationworkings of the C Runtime.

Windows isn't nice enough to provide your app with a ready-made argc and argv. All it does is call a void function() specified in the EXE header. And by default, that function is called mainCRTStartup. Here is a simple example:

extern "C" void __cdecl mainCRTStartup()
{
    int argc = _init_args();
    _init_atexit();
    _initterm(__xc_a, __xc_z);         // Call C++ constructors

    int ret = main(argc, _argv, 0);    // Don't handle environment strings

    _doexit();
    ExitProcess(ret);
}

We start by creating argc and argv, which we later pass to main. But before we do that we have to take care of some things, like calling the constructors for static C++ objects.

The same thing happens in GUI programs, except the function is called WinMainCRTStartup. And for DLLs, the true entry point is _DllMainCRTStartup. Unicode programs look for wmainCRTStartup and wWinMainCRTStartup respectively. DllMain appears to stay the same.

C++ Magic

The constructors of static objects don't just call themselves. And Windows is certainly not going to call them for us. So we have to do it ourselves. What do I mean?

class StaticClass
{
public:
    StaticClass() {printf("StaticClass constructor\n");};
    ~StaticClass() {printf("StaticClass destructor\n");};
};
StaticClass staticClass;

void main()
{
    printf("main\n");
}

C++ programmers should automatically expect the output of this program to be:

StaticClass constructor
main
StaticClass destructor

Matt Pietrek has a great explanation in his article, mentioned earlier, under the heading "The Dark Underbelly of Constructors", so I will not bother going into that level of detail here. Suffice it to say that the compiler emits pointers to the constructor functions (actually thunks to constructor functions) in a special ".CRT" section in the object file, which is later merged with the ".data" section. By declaring a pointer to the start and the end of this section, the _initterm function is able to iterate over these pointers, calling each constructor in turn.

The constructor thunk function also registers an atexit callback to call the destructor of the object. Thus the mainCRTStartup function above goes to the trouble of creating an atexit table. The _doexit function is responsible for calling these functions.

Standard Functions

So now we have taken care of the program's entry point. What about the other functions?

printf and Family

One of the more complex tasks performed by the C Runtime is parsing the printf format string. (I'll admit it's not terribly complex; it's just non-trivial compared to strcmp) To save space, we can offload this processing to the Windows function wvsprintf. No, that's not a wide-character version. The w probably stands for Windows.

extern "C" int __cdecl printf(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    int ret = vprintf(fmt, args);
    va_end(args);

    return ret;
}

extern "C" int __cdecl vprintf(const char *fmt, va_list args)
{
    char bfr[2048];                // ugly... but this whole idea of replacing
                                   // the CRT could be called ugly too!
    int ret = wvsprintf(bfr, fmt, args);

    fwrite(bfr, ret, 1, stdout);   // fwrite takes care of CRLF translation
    return ret;
}

File I/O

Originally I had planned to eschew the FILE structure altogether - and instead just use a HANDLE cast to a FILE*. But this would have only given me two bits of information. As I added functionality to the library this ideal solution became less ideal when I needed to store an end-of-file flag, text-mode flag, and possibly other data. And besides, not using the FILE structure means that the stdin, stdout, and stderr identifiers don't work! So now I (ab)use the FILE structure.

Because I cannot change the FILE structure itself (it is defined in stdio.h) I have to use its fields to work with my data. A very ugly solution. But this library isn't intended to be pretty. NOTE however, that this means code that relies on internal fields in the FILE structure will crash. But then again, you shouldn't be messing with internal data structures anyways, right?

Thus, for illustration, here is fopen:

extern "C" FILE *fopen(const char *path, const char *attrs)
{
    DWORD access, disp;
    if (strchr(attrs, 'w'))
    {
        access = GENERIC_WRITE;
        disp = CREATE_ALWAYS;
    }
    else
    {
        access = GENERIC_READ;
        disp = OPEN_EXISTING;
    }

    HANDLE hFile = CreateFileA(path, access, 0, 0, disp, 0, 0);
    if (hFile == INVALID_HANDLE_VALUE)
        return 0;

    _FILE *file = new _FILE;
    memset(file, 0, sizeof(_FILE));
    file->set_handle(hFile);

    if (strchr(attrs, 't'))
        file->_flag |= _FILE_TEXT;

    return file;
}

fread and fwrite are substantially more complicated than this, because they must translate '\r\n' combinations to '\n' only. For brevity, I will not discuss the algorithm - see the source code if you are interested.

String functions

Replacing the CRT means no more strlen, strcmp, or even memset. These must be implemented from scratch. Thankfully, they are not difficult to implement - just tedious. Care should be taken to handle NULL pointers and other special cases described in the MSDN documentation.

Wide Character (Unicode) Support

This is the major new feature in this library. It is still under development and hasn't undergone extensive testing yet.

As suggested by Hans Dietrich I have started to add wide-character support to the library. Basically that means implementing wide-character versions of various functions.

Uppercase and lowercase

When dealing with ASCII, functions like isalpha, toupper, and strlwr are trivial to implement. But as soon as Unicode enters the picture, they become much more complicated. There are different rules for uppercase versus lowercase and alphabetic versus numeric, so some operating system help is in order. To fix this problem, the function GetStringTypeW is used to implement the isXYZ family of functions, and the functions CharUpper and CharLower are used to implement toupper and tolower, respectively.

File encoding

Up until VS2005 even the Unicode file library functions could only write ASCII characters. Output to wprintf, fwprintf, and fwputs in text mode are all translated from Unicode before it is written to the file.

Because adding support for UTF-8, UTF-16, and other forms of file encoding would just add bloat to this library, I have made the decision to not include it. The behavior will remain compatible with the pre-VS2005 CRT. If you need to deal with file encodings, you probably need the full CRT anyway.

Why are you adding all this stuff? Why not keep it simple!

Simple: Only the stuff that you call is included in a release build!

But then why is Microsoft's CRT so bloated if you don't call much stuff? Again - because you do, but don't know it. The CRT startup code itself calls lots of functions that in turn call other functions - and a lot of it is garbage that isn't needed 90% of the time. Locales, exception handling, etc. have their place, but not in all programs. If your program doesn't use it, why should it have to pay the price of Microsoft's startup code using it?

The startup code and various functions in this CRT library are designed to rely on as little functionality as possible. Thus only the essentials are included.

Using the code

Add the tlibc (Tiny Libc) project to your project's solution, and add it as a referenced project. Alternatively, compile the library and add it to your project's linker options.

Because we are replacing the default CRT, C++ exception handling and SEH will not be handled properly. So don't use it! You will also need to turn off Buffer Security Check, set Runtime Checks to default, and disable Runtime Type Information.

Make sure to link with Ignore Default Libraries turned on! And to generate the smallest code, compile with link-time code generation on, optimize for size, turn string pooling on, and enable COMDAT folding and eliminate unreferenced data.

Results

After recompiling the program with libctiny and the method above, the EXE jumped from a giant 64K to a much more reasonable 4K! (4096 bytes to be exact). For comparison, the entire code section of the linker map file is reproduced below:

 0001:00000000       ?DumpFile@@YAXPAD@Z        00401000 f   hd.obj
 0001:0000013d       _main                      0040113d f   hd.obj
 0001:0000021a       _fopen                     0040121a f   libct:file.obj
 0001:000002a7       _fread                     004012a7 f   libct:file.obj
 0001:000003c2       _fwrite                    004013c2 f   libct:file.obj
 0001:0000048b       _fgetc                     0040148b f   libct:file.obj
 0001:000004b6       _printf                    004014b6 f   libct:printf.obj
 0001:000004ef       _memset                    004014ef f   libct:memory.obj
 0001:0000050e       __doexit                   0040150e f   libct:initterm.obj
 0001:0000053a       _mainCRTStartup            0040153a f   libct:crt0tcon.obj
 0001:000005f5       _malloc                    004015f5 f   libct:alloc.obj
 0001:00000607       __init_args                00401607 f   libct:argcargv.obj
 0001:00000705       __ismbcspace               00401705 f   libct:isctype.obj

History

2007-03-25

  • Fixed strnicmp, pointed out by mpj

2006-08-19

  • Wide-character bugfixes (_fgetws)
  • Non-Unicode builds now set to SBCS rather than MBCS
  • Fixed typo bug in stderr, pointed out by Hans

2006-08-13

  • Preliminary wide-character support
  • Fixed memory leak in command-line parsing (existed in original)
  • Fixed memory leak in fread
  • Fixed behavior of feof
  • Fixed a rather embarrassing problem with strncpy
  • Added _DllMainCRTStartup that I accidentally omitted

2006-08-12

  • Submission to CodeProject

Comments, complaints, questions, etc. are welcome. Please let me know if you actually use this for something. If you need a function that is not included in this library, let me know and I will update the code. Comments on my 'comments' are also welcome.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Mike_V
United States United States
Member
Mike_V is currently a student at UCLA.
 
After a few years on the Dark Side, he reformed and now chants "Death to VB." His computer-related interests include C++, C#, and ASP.NET (in C#, of course). He writes operating systems in C++ and assembler as a hobby.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralWeird thing compiling for 64 bit with .rdata sectionmemberChimpy2010 Apr '10 - 22:20 
In order to remove some link warnings (LNK4254) when using this lib with a 64 bit program I am writing, I had to remove the write attribute from the lines
 
#pragma section(".CRT$XCA", read, write )
 
and
 
#pragma section(".CRT$XCZ", read, write ).
 
in the file initterm.cpp. This seems to work alright although I don't quite know what this bit of code is doing!
 
I'm using Visual Studio 2010 RC.
 
Thanks.
GeneralMany thanks!membermonoceres1 Feb '10 - 4:22 
I've saved ~100 kB thanks to your code! Having exe's ~4 kB that are completely standalone is a bliss!
QuestionTiny C problemsmemberT800G13 Oct '09 - 11:16 
I recently "discovered" Tiny C compiler and it's great (leanest non-assembler code I've seen), but.... Frown | :(
It seems that out-of-the-box compiler (from official web site) has a problem with windows-GUI-subsystem CRT startup code (console crt seems to work ok) because even simple "hello world" test is falsely detected as a virus ("Zhelatin" variant). Dead | X|
 
If I leave WinMain empty all is ok, but insert any external function, eg. MessageBox, and it is instantly detected by antivirus.
I tested compiled windows binary at Virustotal.com and nearly all(!) out of 41 antivirus program detected a malware.
Somehow it comes down to 13 (less prominent vendors) out of 41 if I recompile tcc from source and change one if-block condition in tcc-0.9.25.tar.bz2\tcc-0.9.25\win32\lib\wincrt1.c like this:
 
int _winstart(void)
{
char *szCmd; STARTUPINFO startinfo;
 
__set_app_type(__GUI_APP);
_controlfp(0x10000, 0x30000);
 
szCmd = GetCommandLine();
if (szCmd!=NULL)//<----eliminates some AV false positives

 
but clearly problem goes deeper than one code block.
I tried to build libtcc1.a with gcc but the further I go the more problems emerge(mostly function linking related).
Since I can't fix it myself (and don't have so much spare time) I hope maybe someone can help resolve this issue.
AnswerRe: Tiny C problemsmemberfreesaif1 Jan '10 - 13:36 
Hi,
 
I'm currently stop developing my project because i have this problem, Kasper-sky Anti-virus detect my .exe compiled by tcc as a virus, that Anti-virus software is stupid really
 
I test your solution "if (szCmd!=NULL)", but Kasper-Sky detect it again, please if your find a good solution post it here or send my a email ( freeseif [AT] live [DOT] com )
 
Thank You
GeneralRe: Tiny C problemsmemberDavid 'dex' Schwartz9 Dec '10 - 14:49 
Virus checkers may also be looking for code that is missing.
In the case of programs linked with Tiny C, a lot of expected code is missing.
Keep it simple
dex

Generallibct.lib(sprintf.obj) : error LNK2001: unresolved external symbol _vsprintfmemberMember 603819610 May '09 - 1:27 
The following code fragment causes some errors.
UINT step, totsteps;
endpointVolume->GetVolumeStepInfo(&step, &totsteps);
 
char buffer[200];
sprintf(buffer, "Step: %d, Total amount of steps: %d", step, steps);
 
MessageBox(NULL, buffer, "step", MB_OK);
 
itoa(totsteps, buffer, 10);
 
MessageBox(NULL, buffer, "total steps", MB_OK);
 
Output:
1>------ Build started: Project: myProject, Configuration: Release Win32 ------
1>Compiling...
1>code.cpp
1>.\code.cpp(30) : warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:\Program\Microsoft Visual Studio 9.0\VC\include\stdio.h(366) : see declaration of 'sprintf'
1>.\code.cpp(34) : warning C4996: 'itoa': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _itoa. See online help for details.
1>        c:\Program\Microsoft Visual Studio 9.0\VC\include\stdlib.h(862) : see declaration of 'itoa'
1>Linking...
1>   Creating library Release/myProject.lib and object Release/myProject.exp
1>code.obj : error LNK2001: unresolved external symbol _itoa
1>libct.lib(sprintf.obj) : error LNK2001: unresolved external symbol _vsprintf
1>Release/myProject.dll : fatal error LNK1120: 2 unresolved externals
1>Build log was saved at "file://xxx\BuildLog.htm"
1>myProject - 3 error(s), 2 warning(s)
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========
 
What am I doing wrong here?
GeneralRe: libct.lib(sprintf.obj) : error LNK2001: unresolved external symbol _vsprintfmemberMember 603819612 May '09 - 0:05 
Got another one:
 
1>code.obj : error LNK2001: unresolved external symbol __ftol2_sse
 
Might be some relevant info about this one here: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=107716[^]
GeneralMore Windows-API string functions available!memberDmitry Zemskov14 Apr '09 - 5:29 
There are some more Windows-API string functions in Shlwapi.dll (Shlwapi.h is the header). They include StrStr, StrChr and more. Why not use them instead of writing new code?
(I consider you simply didn't know about their existence).
GeneralHere is missing strtok()memberkr.kim7 Feb '09 - 0:07 
Nice lib,but i met link error with strtok,so i wrote strtok in string.cpp,
 
char *strtok(char *_str,const char*delim)
{
static char *ep;
char *bp;
if(_str)
ep = _str;
bp = ep;
if(*ep == 0)
return 0;
 
while(*ep){
if(strchr(delim,*ep)){
*ep++ = 0;
while(*ep && strchr(delim,*ep)) ep++;
break;
}
ep++;
}
return bp;
}
GeneralNice,tiny bug in strstrmemberkr.kim31 Jan '09 - 21:05 
I found tiny bug in strstr line 9,
 
Original:
 
if (!strcmp(&str[i], substr))
 
Change To:
 
if (!strncmp(&str[i], substr,substr_len))
 

Other Question:
is it compatible with STL ?
it was not compatible with STL when i tested( i hope use vector,...etc).
is it correct?
 
Thank you! Laugh | :laugh:
Generalunresolved symbols on vs2008membernicocode31 Jan '08 - 10:46 
Hi
i'm trying to use the lib together with pixeltoaster (http://www.pixeltoaster.com)
i get several unresolved symbols (see below)
 
1) what's it about with the __RTC_* stuff? isn't it something with the realtime clock,
can it be removed?
2) any advice on how to locate the _Direct3DCreate9 function by dynamically loading the
directx9 dynamic link lib?
3) how to disable the usage of the security_check cookie?! (main offender)
4) the vftable is the virtual function table is there any luck to get rid of it /declare it/ support it by tlibc?
 
i'd be glad to get help on this,
the pixeltoaster library has support for floating High Dynamic Range image buffers which
i completely disabled per #define (ie. no floating point calcs possible)
thanks in advance

Error 6 error LNK2019: unresolved external symbol __RTC_CheckEsp referenced in Error 7 error LNK2001: unresolved external symbol __RTC_CheckEsp
Error 8 error LNK2019: unresolved external symbol @_RTC_CheckStackVars@8
Error 9 error LNK2001: unresolved external symbol @_RTC_CheckStackVars@8
Error 10 error LNK2001: unresolved external symbol __RTC_Shutdown
Error 12 error LNK2001: unresolved external symbol __RTC_InitBase
Error 13 error LNK2001: unresolved external symbol __RTC_InitBase
 
Error 15 error LNK2001: unresolved external symbol "const type_info::`vftable'" (??_7type_info@@6B@)
Error 16 error LNK2001: unresolved external symbol "const type_info::`vftable'" (??_7type_info@@6B@)
Error 17 error LNK2019: unresolved external symbol ___security_cookie referenced in function "union PixelToaster::TrueColorPixel * __cdecl load(char const * const,int &,int &)" (?load@@YAPATTrueColorPixel@PixelToaster@@QBDAAH1@Z) main.obj
Error 18 error LNK2001: unresolved external symbol ___security_cookie PixelToaster.obj
Error 19 error LNK2019: unresolved external symbol @__security_check_cookie@4 referenced in function "union PixelToaster::TrueColorPixel * __cdecl load(char const * const,int &,int &)" (?load@@YAPATTrueColorPixel@PixelToaster@@QBDAAH1@Z) main.obj
Error 20 error LNK2001: unresolved external symbol @__security_check_cookie@4 PixelToaster.obj
Error 21 error LNK2019: unresolved external symbol _Direct3DCreate9@4 referenced in function "public: __thiscall PixelToaster::WindowsDisplay::WindowsDisplay(void)" (??0WindowsDisplay@PixelToaster@@QAE@XZ) PixelToaster.obj blubber
Error 22 error LNK2019: unresolved external symbol __imp___wassert referenced in function "public: __thiscall PixelToaster::WindowsWindow::WindowsWindow(class PixelToaster::DisplayInterface *,class PixelToaster::WindowsAdapter *,char const * const,int,int)" (??0WindowsWindow@PixelToaster@@QAE@PAVDisplayInterface@1@PAVWindowsAdapter@1@QBDHH@Z) PixelToaster.obj
Error 23 error LNK2019: unresolved external symbol __ftol2_sse referenced in function "public: void __thiscall PixelToaster::WindowsWindow::zoom(float)" (?zoom@WindowsWindow@PixelToaster@@QAEXM@Z) PixelToaster.obj
 
i can avoid the printf however:
Error 14 error LNK2019: unresolved external symbol __imp__printf referenced in function "public: int __thiscall Application::run(void)" (?run@Application@@QAEHXZ)

GeneralRe: unresolved symbols on vs2008memberMike_V31 Jan '08 - 12:53 
So some of these look like VS2008 expands the list of runtime checks it uses. Unfortunately the CRT is very compiler-specific, so it looks like VS2008 expands the list of runtime checks available.
 
Becuase I have virtually no time to work on this, and I intended this to be more of an "under the hood" type of article, I will not be able to update this project. Sorry about that. But it sounds like your project needs the full CRT functionality anyways, so it shouldn't be too bad using that.
 
Mike
GeneralRe: unresolved symbols on vs2008membernicocode1 Feb '08 - 6:04 
Thanks for the answer,
I managed to get down to these two last errors:

error LNK2001: unresolved external symbol "const type_info::`vftable'" (??_7type_info@@6B@) error LNK2001: unresolved external symbol _Direct3DCreate9@4

By simply linking against the DLL Runtime Library instead of the application rtl and
switching off the security cookie feature.
I can understand that you don't have the time (same for me when i'd like to do some fun stuff , ie. small computer graphics animations)
I think i'll get the single directx call done on my own, however,
i'd greatly appreciate any hints in getting the vftable reference resolved somehow.
after that just the directsound stuff is missing - the goal is to keep it smaller than 64k
best regards
nico
AnswerRe: unresolved symbols on vs2008membernicocode1 Feb '08 - 6:37 
the vftable linking error can be omitted by disabling the RTTI generation of the
compiler i found out, no runtime type info - no vftable resolve probs!
so issue solved, thanks anyhow -- perhaps i was just too fast in posting here
have a nice weekend
GeneralBug fix in fgetwsmemberPaul Sanders (AlpineSoft)9 Oct '07 - 4:08 
Hi all,
 
Very handy tiny library. Thanks very much.
 
Small buglet in fgetws. Looks like a simple oversight. Change 1st line to:
    if (s->_flag & _FILE_TEXT)
Also, change:
    fgets(bfr, n, s);
to:
    if (fgets(bfr, n, s) == NULL)
        return NULL;
 
Paul Sanders
http://www.alpinesoft.co.uk[^]
GeneralC compilationmembershguillon19 Sep '07 - 5:30 
I have compiled the code in c with some modifications (removing "extern C") and I've tried to run a small program but it crashes.
 
I tried to compile it with
 
BOOL WINAPI DllMain(HANDLE hInst, DWORD reason, LPVOID imp);
 
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, DWORD reason, LPVOID imp)
{......
 
specified in the crt0tdll file but it gives me an error that _DllMainCRTStartup is an unresolved external. I have specified my _DllMainCRTStartup in my DEF file as an export.
It only compiles when I code it like this:
 
BOOL WINAPI DllMain(HANDLE hInst, DWORD reason, LPVOID imp)
{
return TRUE;
}
 
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, DWORD reason, LPVOID imp)
{......
 

And I also have a problem when I link my tyny library to generate an exe. In my testing program I have only
 
int main(int argc, char *argv[])
{
return 0;
}
 
and when I compile it and run it, my program crashes...
 
I would appreciate any advices or comments.
 
Thanks

QuestionDllMainCRTStartup Unresolved External Symbolmembershguillon12 Sep '07 - 9:39 
I am trying to use your article and some of your code to implement an small executable linked to a dll. I get the error Unresolved external symbol '__DllMainCRTStartup@8...at compilation. I am using a DEF file for the exports where I define my DllMainCRTStartup like this:
EXPORTS
"_DllMainCRTStartup" = DllMainCRTStartup@8
 
Is there anything else I need to do, or What am I doing wrong?
 
Many Thanks...
Generalx64memberAbsolute Zero10 Jul '07 - 23:32 
Any chance for a 64bit compilable update?
GeneralRe: x64memberGreenReaper18 Nov '08 - 9:37 
To make this library x64 compatible you can add:
 
#ifndef _M_X64
...
#endif
 
around _CIacos() and _ftol2() in math.cpp
 
To avoid the need for _ftol2() you can use the compilation paramater /QIfist, just read this first:
http://msdn.microsoft.com/en-us/library/6d9xx1d2%28VS.80%29.aspx
It is unlikely to affect people using this for small quick apps.
 
A better way would be to separate out the assembly code into a MASM file but then you'd need to compile it with that.
Generalfew comments about file size and securitymemberamirman6 Apr '07 - 6:05 
1. if you wish to save size:
- you can compile with /align:16
- open your PE file with an hex editor and cut out the null's in the end of the file
- just use a packer (like UPX)
 
2. the implementation of *printf's uses a constant buffer of 1024 bytes.
while this might just end up as a bug in a program (which would be quite hard to detect)
it posses a huge security threat,
using any of the printf's leads almosty every time to an easily exploitable
stack based buffer overflow
 
Amir T.
GeneralRe: few comments about file size and securitymemberMike_V6 Apr '07 - 12:37 
1. /align:16 isn't necessarily supported on all Windows systems. Some (albeit the older ones) require 512 or 4096-byte alignment.
 
Cutting out the nulls at the end of the file is hack-ish at best, and I would _never_ consider doing that even for one of my personal projects.
 
Executable packers make debugging difficult if not impossible, make your program look suspicious (at least in my eyes), and add a step to the build process.
 

2. That would be a "huge security threat" if I just blindly passed the buffer to the underlying function. I do not, and instead truncate the string if it is too large.
 

Keep in mind the stated purpose of this article. This is an advanced trick that will work for some programs to cut their size down significantly, more than any other of the methods in (1) can. It is not intended to be used blindly, but rather to only be used after studying its limitations. It cannot be a drop-in replacement for the Microsoft CRT. If it was, then it would by definition have to implement everything the Microsoft CRT does.
 
Thanks for the feedback,
Michael
Generalsaving a few bytesmemberluc raymond5 Apr '07 - 2:24 
for those who wish to save a few bytes with/without using this library, you can go into your project's option, under Linker->Optimization->Optimize for Windows 98: change it from DEFAULT to NO.
 
You will save around 11k
 
Luc raymond
http://www.virtualshowcar.com
http://www.lucraymond.net
http://www.woxxom.com

QuestionIntrinsic InteroperabilitymemberRob Grainger4 Apr '07 - 2:03 
Great article - I remember spending a little time investigating how the static constructors worked myself. Seems a shame Microsoft didn't adopt this approach with the _ATL_MIN_CRT version of ATL, I've suffered there from avoiding static objects.
 
One question - have you considered/tested interoperation with intrinsic versions of various functions? The VS2005 C++ compiler has option for generating intrinsic versions of memcpy and other functions suitable for tight inlining. Can we still utilise these with the Tiny C Runtime Library?
 
Once again - congrats - excellent article.
AnswerRe: Intrinsic InteroperabilitymemberMike_V4 Apr '07 - 8:01 
I would assume so, although I have not personally tested it myself. Projects I create using this are optimized for size (obviously) which turns off intrinsics.
 
Mike
GeneralA bit scarymembernorm .net25 Mar '07 - 23:38 
I can't image all the black box testing that would have to be done so this could be reiably used in production code, but the idea and article have good value.
 
.net is a box of never ending treasures, every day I get find another gem.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 25 Mar 2007
Article Copyright 2006 by Mike_V
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid