c-这个版本中的错误发生在哪里



我不是一个C程序员,所以我意识到我有点不知所措。

如何定位此错误发生的位置并确定它是什么?在我看来,这是make命令的相关输出。

gmake --debug=jv
. . . 
Putting child 0x8006e6600 (/home/byrnejb_hll/Projects/AB4-1/aubit4glsrc/lib/libaubit4gl-1.5_3.so) PID 77727 on the chain.
Live child 0x8006e6600 (/home/byrnejb_hll/Projects/AB4-1/aubit4glsrc/lib/libaubit4gl-1.5_3.so) PID 77727 
/usr/local/bin/ld: keys.o:/home/byrnejb_hll/Projects/AB4-1/aubit4glsrc/incl/a4gl_libaubit4gl.h:1026: multiple definition of `abort_pressed'; fglwrap.o:(.bss+0xe0): first defined here
/usr/local/bin/ld: report.o: in function `A4GL_internal_open_report_file':
/usr/home/byrnejb_hll/Projects/AB4-1/aubit4glsrc/lib/libaubit4gl/report.c:764: warning: warning: tmpnam() possibly used unsafely; consider using mkstemp()
collect2: error: ld returned 1 exit status
Reaping losing child 0x8006e6600 PID 77727 
gmake[2]: *** [Makefile:211: /home/byrnejb_hll/Projects/AB4-1/aubit4glsrc/lib/libaubit4gl-1.5_3.so] Error 1
Removing child 0x8006e6600 PID 77727 from chain.
gmake[2]: Leaving directory '/usr/home/byrnejb_hll/Projects/AB4-1/aubit4glsrc/lib/libaubit4gl'
Reaping losing child 0x8006d2960 PID 77684 
gmake[1]: *** [Makefile:276: libaubit4gl-1.5_3.so] Error 2
Removing child 0x8006d2960 PID 77684 from chain.
gmake[1]: Leaving directory '/usr/home/byrnejb_hll/Projects/AB4-1/aubit4glsrc/lib'
Reaping losing child 0x8006e4200 PID 77600 
gmake: *** [Makefile:285: corecompile] Error 2
Removing child 0x8006e4200 PID 77600 from chain.

中的代码/lib/libaubit4gl.h是:

1024 #ifdef OBJECTMODULE$
1025   char opts[100][80];^I^I/*menu options */$
1026   int abort_pressed;$
1027   int relxedit = 0, relyedit = 0;$
1028   int aborted;$
1029   long time_offset = 0;$
1030   int week_no = -1;$
1031   struct s_form_attr std_dbscr;$
1032 #else$
1033   extern char opts[10][80];^I/*menu options */$
1034   extern int abort_pressed;$
1035   extern int relxedit, relyedit;$
1036   extern int aborted;$
1037   extern long time_offset;$
1038   extern int week_no;$
1039   dll_import struct s_form_attr std_dbscr;$
1040 #endif$

这是唯一提到abort_pressed的地方。

fglwrap.c中的代码,也是唯一使用abort_pressed的地方

1450 void$
1451 A4GL_def_quit (void)$
1452 {$
1453 #ifdef DEBUG$
1454   A4GL_debug ("FIXME: DEFER QUIT NOT IMPLEMENTED - Setting quit mode");$
1455 #endif$
1456 }$
1457 $
1458 int abort_pressed=0;$
1459 $
1460 /**$
1461  *$
1462  * @todo Describe function$
1463  */$
1464 void$
1465 A4GL_set_abort (int a)$
1466 {$
1467 #ifdef DEBUG$
1468   A4GL_debug ("set_abort called with %d", a);$
1469 #endif$
1470   abort_pressed = a;$
1471 }$
1472 $

正确的处理方法是什么?我正试图让一个曾经有效的程序重新运行,但我不是作者。

是的,所以看起来有多个";abort_ pressed";,其来源于a";。h〃;文件(头文件(。您不应该在.h文件中定义变量,只需声明它们即可。如果只包含一次.h文件,则可以避免此错误,但如果包含两次,则会出现此错误。

研究声明和定义之间的区别,并将定义从.h文件中移出。这是用C进行编码的最佳实践,即使您只需要在一个地方包含.h文件

至于发生的机制,编译器会将所有的.h文件复制并粘贴到任何包含它们的地方,即"#包括";header.h";将把header.h的所有代码粘贴到它写的任何地方。您可以多次声明,即声明一个函数";数学"-

void math(uint8_t val);

这样的东西可以随心所欲地多次写入代码,所以当它们被多次粘贴时,编译器不会感到困惑。然而,当你定义事物时,即定义一个变量";globalFlags";

uint32_t globalFlags;

这会混淆编译器,因为它正在创建一个值";globalFlags";在存储器中,可以通过关键字"来访问;globalFlags";。如果你试图创建第二个版本,编译器会感到困惑,因为它不知道要访问两个内存地址中的哪一个,因为";globalFlags";适用于两者。所以它抛出了一个错误,告诉你修复

这是遗留代码的常见问题。头文件或源文件都定义了一个只应声明的变量。

这来自于传统的UNIX链接模型;C最初并没有纯引用,也并没有extern关键字,和当时的其他语言非常相似。

此外,放在上下文中讲,早期的C没有原型,结构成员名称没有名称空间(这就是为什么像BSD套接字这样的旧接口中的结构成员带有前缀(,而且基本上它不能区分彼此,但通过它们的名称,它在当时真的很原始。

因此,变量将被放在对象文件中的一个(特殊的(公共部分,而不是引用,任何重复的变量都将由链接器通过查看它来合并;如果我没有错的话,遵循FORTRAN使用的方法。

链接器仍然是它的一部分,它处理对象文件,并试图将公共部分中的符号解析为其他符号,最后剩下的所有符号都放在BSS中(未初始化/零数据(。

编译器会在这个公共部分中放入任何临时声明(即没有初始化程序值(。

GCC默认情况下对C采用这种方法,直到GCC 10,它改为与C++相同的方法,即将这些方法直接放入BSS中;公平的事情,因为:

  • 30多年来,我们有更好的方法来处理这个问题
  • 生成的机器代码并不总是最优的
  • unix模型与C标准有点矛盾
  • 无法判断重复的定义是故意的还是偶然的(所以这是一种糟糕的做法(

然而,GCC仍然可以编译未经修改的遗留代码,如果您不能或不愿修改它,只需切换即可:-fcommon

相关内容

最新更新