为什么 lex 中定义的 main 函数被 cc 报告为重复符号?

问题描述 投票:0回答:1

我正在运行“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)

为什么 main 被报告为已经定义的? 这本书提到了 AT&T lex 版本并使用 K&R C,所以我确实理解 lex 的实现可能存在差异,并且这本书可能引用了旧的 lex 实现。

我目前在 FreeBSD 中使用提供的 lex 版本。

c yacc lex
1个回答
0
投票

不要使用

-ll
,因为 lex 库包含
main()
函数实现,或者将其放在已提供
main()
例程之后(如您在
lex.yy.c
中提供的那样),因此 lex 的主模块库不包含在链接中。最好的方法是将库放在最后,这样只有具有未定义引用的模块才会链接到程序中。

改变

lex ch2-04.l; cc -ll -o ch2-04 lex.yy.c 

进入

lex ch2-04.l; cc -o ch2-04 lex.yy.c -ll 

一切都会顺利。

解释: 当链接器看到

-ll
函数时,它已经有一个对
main()
的未解析引用,该引用来自通常首先向编译器指定的 C 运行时环境。所以它包含了Lex库提供的
main()
函数。当您链接文件
lex.yy.c
时,会提供
main()
的第二个版本(这次是您在 lex 源中提供的版本)与之前已链接的版本冲突。

© www.soinside.com 2019 - 2024. All rights reserved.