0

Is there any way I can explicitly in my code call the functions that are normally called in mainCRTStartup functions? I'm specifically interested initterm and initterm_e functions. Even thought my program is linked with crt (it has to be, right?) I couldn't just call initterm - I tried to declare and just invoke and I got undefined reference.

Is there any way to do it?

Marcin K.
  • 683
  • 1
  • 9
  • 20
  • It is not exported so you can't link it. Which is for the better, doing this is unlikely to come to good end. Just restart the program. – Hans Passant Sep 20 '17 at 21:18
  • @HansPassant - no, this api is exported. say by *msvcrt.dll*. and in lib files we can found this names too – RbMm Sep 20 '17 at 21:21
  • *my program is linked with crt* - which *lib* exactly you use ? you need open this lib and search for `initterm` string. think it exist and lib file and undefined reference only because you wrong declared it – RbMm Sep 20 '17 at 21:27
  • for example if use say *ucrt.lib* here exist both *initterm* and was bind to `api-ms-win-crt-runtime-l1-1-0.dll`. in other words to `ucrtbase.dll`. another crt libs can bind to another dlls. and this functions very easy implement yourself too – RbMm Sep 20 '17 at 21:32
  • *Is there any way to do it?* of course yes and very simply - correct declare it and call. or you have problems with input parameters ? like `#pragma const_seg(".CRT$XCA") const _PVFV __xc_a = 0; #pragma const_seg(".CRT$XCZ") const _PVFV __xc_z = 0;` and call `_initterm(&__xc_a, &__xc_z);` – RbMm Sep 20 '17 at 21:40
  • Oh how silly of me. In the declaration I didn't state that its c function (in programming in c++). So the name got mangled. – Marcin K. Sep 20 '17 at 21:51
  • 1
    From the documentation: **"Do not call these methods in a program."** – Harry Johnston Sep 20 '17 at 21:53
  • The real question is; *why* do you want (or need) to do this? – Jesper Juhl Sep 20 '17 at 22:02
  • My project has special requirements that require me to do ugly stuff @RbMm If you would make your comment into answer I would mark it – Marcin K. Sep 20 '17 at 22:34

1 Answers1

3

the _initterm, and _initterm_e (note in msdn _initterm_e is wrong declared - really it used _PIFV type) is exported by different CRT dlls. and it declared in lib files too. and implementation of this functions is very simply:

typedef void (__cdecl *_PVFV)();

void _initterm(const _PVFV *ppfn, const _PVFV *end)
{
    do 
    {
        if (_PVFV pfn = *++ppfn)
        {
            pfn();
        }
    } while (ppfn < end);
}

typedef int  (__cdecl *_PIFV)();

int _initterm_e(const _PIFV *ppfn, const _PIFV *end)
{
    do 
    {
        if (_PIFV pfn = *++ppfn)
        {
            if (int err = pfn()) return err;
        }
    } while (ppfn < end);

    return 0;
}

so you can import it ot use own implementation. here faster question - what is use as input parameters ?

say c++ (CL compiler how minimum) use ( ".CRT$XCA", ".CRT$XCZ" ) sections for place c++ global initializes. so we can do next:

extern "C"
{
#pragma const_seg(".CRT$XCA")
  const _PVFV __xc_a = 0;
#pragma const_seg(".CRT$XCZ")
  const _PVFV __xc_z = 0;

#pragma const_seg(".CRT$XIA")
  const _PVFV __xi_a = 0;
#pragma const_seg(".CRT$XIZ")
  const _PVFV __xi_z = 0;
}

    /*
     * do initializations
     */
    initret = _initterm_e( &__xi_a, &__xi_z );
    if ( initret != 0 )
        return initret;

    /*
     * do C++ initializations
     */
    _initterm( &__xc_a, &__xc_z );

but here need very good understand - what and why we doing

RbMm
  • 31,280
  • 3
  • 35
  • 56
  • Thanks. Just a fast clarification: Shouldnt function pointer be postincremented instead of preincremented? – Marcin K. Sep 21 '17 at 08:55
  • @MarcinK. - i use `__xc_a` as pointer begin. so `ppfn` at begin will be point exactly to `__xc_a` which is 0. so `*ppfn` at begin is 0. preincremented is small optimization. but if use postincrement will be no error – RbMm Sep 21 '17 at 09:11