【发布时间】:2016-12-17 10:59:15
【问题描述】:
C++ 标准表明main 可以有two possible signatures。
int main() // (1)
int main(int, char*[]) // (2)
此外,main() 通常是从__libc_start_main 调用的,它在csu/libc-start.c 源代码中的csu/libc-start.c 中定义。该函数内部对main的调用复制如下。
result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
我们观察到这里的调用使用了三个参数,这似乎不会产生任何链接器错误,尽管签名与上述两种形式都不匹配。
我正在编写一个定义main() 的线程库,并希望应用程序能够定义以下两个函数之一。
int AppMain() // (1)
int AppMain(int, char*[]) // (2)
不幸的是,如果我使用上面的第二种形式声明 AppMain 并从我的库的 main 调用它,而应用程序使用第一种形式,那么我得到一个未解决的引用链接器错误,表明我调用的函数确实不存在。
由于相对于main,这对于glibc 来说似乎不是问题,我怎样才能以一种避免链接器错误的方式编写我的调用或声明?
这是重现问题的简单方法。
生成文件
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(工作版)
#include <stdio.h>
int AppMain(int argc, char** argv){
printf("Application says Hello world\n");
return 0;
}
App.cc(非工作版)
#include <stdio.h>
int AppMain(){
printf("Application says Hello world\n");
return 0;
}
在第二个版本下,这里是链接器错误。
./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
【问题讨论】:
-
main()由运行时库专门处理,您无法对常规函数做同样的事情。 -
您应该只要求您的
AppMain()函数始终使用第二个签名。 -
总的来说,我认为您使用了错误的策略。强制使用您的库的开发人员使用您的
main()函数会限制在已经具有main()函数的任何现有应用程序中的采用,如果其他第三方库的代码(例如静态构造)需要在您的库中的代码之前运行,等等。您最好捆绑示例main()函数(在文档中,或不属于库本身的说明性源文件中),以便开发人员适应他们的应用程序。跨度> -
@peter,感谢您的反馈。我对这个决定很矛盾,很高兴获得第二意见。