English 中文(简体)
C诉C++号汇编者将未使用的符号列入物体档案
原标题:Inclusion of unused symbols in object files by compiler in C vs C++

这可能是一个棘手的问题,但也许有人可以提供一些见解。

我在一份标题文件中界定了一些全球变量(即我知道有坏,但这只是一种假设情况)。 我将这一标题档案列入两个来源档案,然后汇编成两个物体档案。 《守则》没有提及全球标志。

如果来文方档案为C,那么它就象汇编者那样将全球符号和所有链接混为一谈,而没有错误。 如果来文方档案为C++,其符号就列入两个物体档案,然后我发现链接错误。 C++ 当我包括头盔时,我正在使用“C”一词。

我正在使用2005年版的微软编辑。

我的守则是:

Header file (test.h):

#ifndef __TEST_H
#define __TEST_H

/* declaration in header file */
void *ptr;

#endif

C. 结 论 资料来源:档案。

测试1.c

#include "test.h"

int main( ) {
    return 0;
}

测试2.c

#include "test.h"

C++ 资料来源:档案。

测试1.cpp

extern "C" {
#include "test.h"
}

int main( ) {
    return 0;
}

测试2.cpp

extern "C" {
#include "test.h"
}

对C而言,物体档案类似:

Dump of file test1.obj

File Type: COFF OBJECT

COFF SYMBOL TABLE
000 006DC627 ABS    notype       Static       | @comp.id
001 00000001 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   2F, #relocs    0, #linenums    0, checksum        0
004 00000000 SECT2  notype       Static       | .debug$S
    Section length  228, #relocs    7, #linenums    0, checksum        0
006 00000004 UNDEF  notype       External     | _ptr
007 00000000 SECT3  notype       Static       | .text
    Section length    7, #relocs    0, #linenums    0, checksum 96F779C9
009 00000000 SECT3  notype ()    External     | _main
00A 00000000 SECT4  notype       Static       | .debug$T
    Section length   1C, #relocs    0, #linenums    0, checksum        0

String Table Size = 0x0 bytes

而对于C++,他们看着这样的情况:

Dump of file test1.obj

File Type: COFF OBJECT

COFF SYMBOL TABLE
000 006EC627 ABS    notype       Static       | @comp.id
001 00000001 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   2F, #relocs    0, #linenums    0, checksum        0
004 00000000 SECT2  notype       Static       | .debug$S
    Section length  228, #relocs    7, #linenums    0, checksum        0
006 00000000 SECT3  notype       Static       | .bss
    Section length    4, #relocs    0, #linenums    0, checksum        0
008 00000000 SECT3  notype       External     | _ptr
009 00000000 SECT4  notype       Static       | .text
    Section length    7, #relocs    0, #linenums    0, checksum 96F779C9
00B 00000000 SECT4  notype ()    External     | _main
00C 00000000 SECT5  notype       Static       | .debug$T
    Section length   1C, #relocs    0, #linenums    0, checksum        0

String Table Size = 0x0 bytes

我注意到,在我汇编C资料来源时,“接收器”被列为“紧急应急中心”,在我汇编C++来源时加以界定,造成联系错误。

我的理解是,这不是在现实生活中做的一件好事,我只是想理解为什么情况不同。

感谢。

最佳回答

在C,识别器有三种不同的“链接”类型:

  1. external linkage: roughly, this is what people mean by "global variables". In common terms, it refers to identifiers that are visible "everywhere".
  2. internal linkage: these are objects that are declared with static keyword.
  3. no linkage: these are objects that are "temporary", or "automatic", such as variables declared inside a function (commonly referred as "local variables").

对于有外部联系的物体,你只能有one的定义。 由于贵方的档案界定了这种物体,并包含在两个C档案中,因此,它不明确(但见下文)。 你的C编纂者没有抱怨,这并不意味着在C这样做是大韩民国的。 为此,你必须读到C标准。 (Or,如果以符合标准的方式援引,在您的汇编者中不作弊,如果它抱怨某种东西[诊断],则很可能意味着你的方案符合标准。)

换言之,如果贵国的汇编者允许,你可以测试语言允许的内容。 为此,你必须读到标准。

注:定义与tentative定义之间有微妙的区别。

$ cat a.c
int x = 0;
$ cat b.c
#include <stdio.h>
int x = 0;
int main(void)
{
    printf("%d
", x);
    return 0;
}
$ gcc -ansi -pedantic -W -Wall -c a.c
$ gcc -ansi -pedantic -W -Wall -c b.c
$ gcc -o def a.o b.o
b.o:(.bss+0x0): multiple definition of `x 
a.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status

现在请改动<代码>a.c:

$ cat a.c
int x; /* Note missing " = 0", so tentative definition */

现将其汇编成册:

$ gcc -ansi -pedantic -W -Wall -c a.c
$ gcc -o def a.o b.o
$ ./def
0

我们可以修改<代码>b.c。 相反:

$ cat a.c
int x = 0;
$ cat b.c
#include <stdio.h>
int x; /* tentative definition */
int main(void)
{
    printf("%d
", x);
    return 0;
}
$ gcc -ansi -pedantic -W -Wall -c a.c
$ gcc -ansi -pedantic -W -Wall -c b.c
$ gcc -o def a.o b.o
$ ./def
0

如果没有其他定义,“暂定定义”就成为C中的“真实定义”。 因此,我们本可以修改这两份文件,以列入<代码>int x;,这将是法律C。

因此,您在标题档案中可能有一个暂定定义。 我们需要确保实际守则。

C标准指出,以下行为不明确(附录J.2p1):

An identifier with external linkage is used, but in the program there does not exist exactly one external definition for the identifier, or the identifier is not used and there exist multiple external definitions for the identifier.

C++可能有不同的规则。

,在comp.lang.c++上读,C++没有tentative definition <>。 理由是:

这避免了在固定类型和用户界定的类型方面有不同的初始化规则。

(主线处理的是同一问题,tw)

现在,我几乎确信,《任择议定书》的法典包含标题档案中C所说的“暂定定义”,因此在C中是合法定义,在C++中是非法的。 我们只有在看到该守则时才会知道。

关于“暂定定义”以及为何需要这些定义的更多信息,见excellent post on comp.lang.c(由Chris Torek主)。

问题回答

Don t界定了头脑中的变数——即邪恶。

标题中只公布变数——有明确的<代码>extern关键词。

不同之处在于,C++明确要求有一个定义规则——在C++方案中,可能只有一个定义,对任何特定变量有外部联系。

严格地说,C标准有相同的要求。 然而,附录 在标准表J中,允许将多种未采用的定义视为一种通用定义,即所谓的共同定义,因为它类似于(旧学校)Fortran(例如,Aka Fortran 66和Agtran 77)的COMMON区的行为。


Caveat: 是,如果你知道不需要提出这些问题的话,有时很少,但偶尔也只是偶然地成为在头脑中确定变数的理由。 但是,在“在头盔中确定变数”这两者之间,这种机会很少,而且很远。


Christoph raises an interesting point about static const variables . One weasel-wording way around the issue is to claim that "a constant isn t a variable". However, Christoph is right: in C++ in particular, static const variables are used. In C, I thought such constants would tend to elicit unused warnings from compilers; however, GCC 4.4.2 does not give any warnings when given this minimal code:

static const int x = 3;
extern int p(void);
int p(void)
{
    return(3);
}

它不抱怨未使用的<代码>x。 甚至在<代码>-Wall-Wextra下。 因此,由大韩民国确定头盔的固定数——如<代码>中。 部分 类型ConstName = 初始Value;。 至少,如果您的汇编者是海合会,但该守则还汇编了Sunudio汇编器的无警告材料,并附有cc-v:

C compiler: /compilers/v12/SUNWspro/bin/cc
cc: Sun C 5.9 SunOS_sparc Patch 124867-09 2008/11/25
acomp: Sun C 5.9 SunOS_sparc Patch 124867-09 2008/11/25
iropt: Sun Compiler Common 12 SunOS_sparc Patch 124861-13 2009/03/10
cg: Sun Compiler Common 12 SunOS_sparc Patch 124861-13 2009/03/10
ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.486




相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签