You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 13:22:45