【问题标题】:"multiple definition of value" when compiling C program with uninitialized global in g++ but not gcc使用g ++中未初始化的全局而不是gcc编译C程序时“值的多重定义”
【发布时间】:2012-11-15 19:15:51
【问题描述】:

我试图了解外部和全局变量声明在头文件中的用法,所以我想出了以下用 C 编写的测试程序。

main.c 文件

//main.c
#include "global.h"
#include <stdio.h>

int nExternValue = 6;

int main(int argc, char* argv[])
{
    printf("%d \n", nValue);
    printf("%d \n", nExternValue);

    AddToValue();

    printf("%d \n", nValue);
    printf("%d \n", nExternValue);
}

global.h 文件

#ifndef _GLOBAL_H
#define _GLOBAL_H

//WRONG! do not declare a variable here
int nValue;

//OK! extern variable makes it a global accessable variable
extern int nExternValue;

//OK! function prototype can be placed in h file
int AddToValue();

#endif

以及一个实现 AddToValue 函数的 AddValue.c 文件。

#include "global.h"

int AddToValue() {
    nValue++;
    nExternValue++;
}

我使用 gcc 编译了应用程序,然后运行了它:

$ gcc main.c AddValue.c -o test
$./test
0 
6 
1 
7 

我使用 g++ 编译了应用程序并收到以下链接器错误:

$ g++ main.c AddValue.c -o test
/tmp/ccFyGDYM.o:(.bss+0x0): multiple definition of `nValue'
/tmp/cc3ixXdu.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status

为什么 gcc 链接器不产生错误?我虽然 nValue 变量会被声明多次,这会产生错误!

$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

【问题讨论】:

  • 当您在多个 *.c 文件中包含 *.h 文件时,您将声明多次相同的变量。为避免这种情况,最好不要在 *.h 文件中声明全局变量,而是在 *.c 文件中声明。
  • @Kira 我认为这里的问题是为什么 gcc 链接器不会产生多重声明作为错误?
  • @shinkou 确实如此,但这就是为什么我发表评论而不是回答,以防他在等待真实答案时需要解决问题。
  • 感谢 Kira,但我认为您不应该在 .c 文件中声明全局变量。如果声明的变量在 .c 文件中,其他文件如何知道它,除非您建议 #include .c 文件?
  • @ArmenB。 ——查“暂定声明”。那应该回答你的问题。

标签: c++ c linker compiler-errors global-variables


【解决方案1】:

C 和 C++ 是不同的语言。举个例子,上面的程序是一个有效的 C 程序,但在格式错误的 C++ 程序中。您违反了 C++ 的单一定义规则。 C中没有对应的规则。

当使用 gcc 编译时,您将上述文本编译为 C 程序。使用 g++ 编译时,您将上述文本编译为 C++ 程序。

【讨论】:

  • AnT 说它也是无效的 C,虽然在附件 J 中提到了一个常见的扩展名:stackoverflow.com/a/3692486/895245
  • C 具有单一定义规则,该程序也不是有效的 C 程序。 (nValue 有两种定义)。
【解决方案2】:

使用 gcc 编译时,未初始化的全局变量(如 nValue)将被视为通用符号。在不同编译单元中出现的相同公共符号将在链接时合并。如果使用 g++ 编译(这意味着源程序将被视为 C++ 程序),未初始化的全局变量将被隐式初始化为默认值 0。由于 global.h 包含在多个源文件中,编译器将考虑符号 nValue 定义多次。

也请看看这篇文章: Why uninitialized global variable is weak symbol?

【讨论】:

    猜你喜欢
    • 2014-09-20
    • 1970-01-01
    • 2016-06-03
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多