1

The C++ Standard indicates that the main can have two possible signatures.

int main()               // (1)
int main(int, char*[])   // (2)

Moreover, main() is typically called from __libc_start_main, which is defined in csu/libc-start.c in the glibc source code. The invocation of main inside this function is copied below.

result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);

We observe that the call here uses three arguments, and this appears to not produce any linker errors, despite the fact that the signature does not match either of the above two forms.


I am writing a threading library which defines main(), and would like the application to be able to define one of the following two functions.

int AppMain()               // (1)
int AppMain(int, char*[])   // (2)

Unfortunately, if I declare AppMain using the second form above and invoke it from my library's main, and the application uses the first form instead, then I get a unresolved reference linker error indicating that the function I invoked does not exist.

Since this does not seem to be a problem for glibc with respect to main, how might I write my invocation or declaration in a way that avoids the linker error?


Here is an easy way to reproduce the problem.

Makefile

CCFLAGS=-Wall -Werror

all: libLib.a App

libLib.a: Lib.o
    ar rcs $@ $^

App: App.o libLib.a
    g++ -o $@ $< -L. -lLib

%.o: %.cc
    g++ $(CCFLAGS)  -O3 $(LIBS) -fPIC -c  -o $@ $<

Lib.cc

#include <stdio.h>

int AppMain(int argc, char** argv);

#undef main
int main(int argc, char** argv){
    printf("Hello World\n");    
    AppMain(argc, argv);
}

App.cc (Working Version)

#include <stdio.h>

int AppMain(int argc, char** argv){
    printf("Application says Hello world\n");
    return 0;
}

App.cc (Non-Working Version)

#include <stdio.h>

int AppMain(){
    printf("Application says Hello world\n");
    return 0;
}

Under the second version, here is the linker error.

./libLib.a(Lib.o): In function `main':
Lib.cc:(.text.startup+0x24): undefined reference to `AppMain(int, char**)'
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target 'App' failed
make: *** [App] Error 1
Community
  • 1
  • 1
merlin2011
  • 71,677
  • 44
  • 195
  • 329
  • 2
    `main()` is handled specially by the runtime library, there's no way for you to do the same thing for regular functions. – Barmar Dec 17 '16 at 11:40
  • You should just require that your `AppMain()` functions always use the 2nd signature. – Barmar Dec 17 '16 at 11:41
  • Overall, I consider you're using the wrong strategy. Forcing a developer using your library to use your `main()` function constrains adoption in any existing application which already has a `main()` function, make usage of other third-party libraries inconvenient if they have code (e.g. construction of statics) that needs to be run before code in your library, etc etc. You would be better off bundling sample `main()` functions (in documentation, or illustrative source files that are not part of the library itself) that a developer can adapt for their application. – Peter Dec 17 '16 at 11:54
  • @peter, thank you for the feedback. I've been very conflicted about this decision and it's good to get a second opinion. – merlin2011 Dec 17 '16 at 17:51

1 Answers1

0

Regardless of suggestions to do it differently, I just answer your question

how might I write my invocation or declaration in a way that avoids the linker error?

You may write your definition in App.cc as

extern "C" int AppMain()
{
    …

and your declaration in Lib.cc as

extern "C" int AppMain(int argc, char** argv);

to avoid that name mangling, the same as it's most probably done in glibc. There may be C++ compilers where this doesn't work, but it certainly works with the GCC.

Armali
  • 18,255
  • 14
  • 57
  • 171