为何Lex中定义的main函数被cc报重复符号错误?
问题背景
我在运行《Lex & Yacc》(John R. Levine、Tony Mason和Doug Brown 著)中的示例代码:
$ cat ch2-04.l %{ unsigned verbose; char *prog_name; %} %% -h | "-?" | -help { printf("usage is: %s [ -help | -h | -? ] [ -verbose | -v ] [ (-file | -f) filename ]\n", prog_name); } -v | -verbose { printf("verbose mode is on\n"); verbose=1; } %% int main(int argc, char **argv) { prog_name = *argv; yylex(); return 0; }
使用以下命令编译时出现错误:
$ lex ch2-04.l; cc -ll -o ch2-04 lex.yy.c ld: error: duplicate symbol: main >>> defined at libmain.c:29 (/usr/src/contrib/flex/src/libmain.c:29) >>> libmain.o:(main) in archive /usr/lib/libl.a >>> defined at lex.yy.c >>> /tmp/lex-f8aca4.o:(.text+0x1D80) cc: error: linker command failed with exit code 1 (use -v to see invocation)
我使用的是FreeBSD自带的lex版本,书中用的是AT&T lex和K&R C,我知道不同lex实现有差异,但不清楚为什么会提示main函数重复定义。
原因分析
问题核心是不同lex实现的库差异:
- AT&T lex的
libl.a库不包含默认的main函数,因此示例代码需要自行编写main来调用yylex(),这是书中的设计逻辑。 - FreeBSD的lex基于flex,其
libl.a库包含了libmain.o文件,里面已经实现了一个默认的main函数,作用就是调用yylex()。当你通过-ll参数链接这个库时,就会引入这个默认main,和你自己代码中编写的main函数产生重复定义冲突。
解决方法
有两种简单可行的解决方式:
- 编译时不链接
libl.a库:既然你已经自己实现了main函数,就不需要依赖库提供的版本,直接编译生成的lex.yy.c即可:lex ch2-04.l; cc -o ch2-04 lex.yy.c - 移除自己编写的main函数:如果想使用库提供的默认main,需要把
prog_name的初始化逻辑移到其他地方(比如yywrap()函数或者自定义初始化函数),不过这种方式需要修改代码,不如第一种直接。
内容的提问来源于stack exchange,提问作者M.E.
相关产品推荐
相关产品推荐

