English 中文(简体)
令人厌恶地将不相容的类型联系起来会导致混乱。
原标题:Happily linking incompatible types leads to chaos

I ve been trying to figure out some boundaries of g++, especially linking (C++) object files. I found the following curiosity which I tried to compress as much as possible before asking.

Code

文件common.h

#ifndef _COMMON_H
#define _COMMON_H

#include <iostream>

#define TMPL_Y(name,T) 
struct Y { 
  T y; 
  void f() { 
    std::cout << name << "::f " << y << std::endl; 
  } 
  virtual void vf() { 
    std::cout << name << "::vf " << y << std::endl; 
  } 
  Y() { 
    std::cout << name << " ctor" << std::endl; 
  } 
  ~Y() { 
    std::cout << name << " dtor" << std::endl; 
  } 
}

#define TMPL_Z(Z) 
struct Z { 
  Y* y; 
  Z(); 
  void g(); 
}

#define TMPL_Z_impl(name,Z) 
Z::Z() { 
  y = new Y(); 
  y->y = name; 
  std::cout << #Z << "(); sizeof(Y) = " << sizeof(Y) << std::endl; 
} 
void Z::g() { 
  y->f(); 
  y->vf(); 
}

#endif

文件<代码>a.cpp 编辑:<代码>g++ - Wall -c a.cpp

#include "common.h"

TMPL_Y( a ,char);

TMPL_Z(Za);

TMPL_Z_impl( a ,Za);

文件<编码>b.cpp 编辑:<代码>g++ - 安装——c b.cpp

#include "common.h"

TMPL_Y( b ,unsigned long long);

TMPL_Z(Zb);

TMPL_Z_impl( b ,Zb);

文件<代码>main.cpp汇编并与<代码>g++链接 a.o b.o main.cpp

#include "common.h"

struct Y;
TMPL_Z(Za);
TMPL_Z(Zb);

int main() {
  Za za;
  Zb zb;
  za.g();
  zb.g();
  za.y = zb.y;
  return 0;
}

<代码>/a.out的结果

a ctor
Za(); sizeof(Y) = 8
a ctor  // <- mayhem
Zb(); sizeof(Y) = 12
a::f a
a::vf a
a::f b  // <- mayhem
a::vf b // <- mayhem

Question

现在,我本希望<代码>g++>,把试图将<代码>a.o和b.o联接起来的一些新名字叫我。 特别是,<代码>za.y = zb.y的转让是邪恶的。 不仅如此,<条码>g++/代码>根本不抱怨,我希望它把不符合同名称的类型(<条码>Y)联系起来,而且完全忽视了<条码>b.o(resp.b.cpp)中的次要定义。

我指的是我不做些事情:sooo>/em>。 两个汇编单位在一个大型项目中可以使用同一名称。

这难道是一种ug吗? 是否有任何人对这一问题有所了解?

最佳回答

举例来说,你可将Y的定义放在一个匿名的网站上:

#define TMPL_Y(name,T) 
namespace { 
    struct Y { 
      T y; 
      void f() { 
        std::cout << name << "::f " << y << std::endl; 
      } 
      virtual void vf() { 
        std::cout << name << "::vf " << y << std::endl; 
      } 
      Y() { 
        std::cout << name << " ctor" << std::endl; 
      } 
      ~Y() { 
        std::cout << name << " dtor" << std::endl; 
      } 
    }; 
}

这基本上为每个汇编股创造了一个独特的名称空间,实际上,你拥有独特的Y s,联系人将能够正确联系。

说明

za.y = zb.y;

this will still yield unpredictable results of course as the 2 types are incompatible.

问题回答

引用Bjarne Stroustrup的“C++方案编制语言”:

<>9.2 链接<>

所有翻译单位都必须一致使用职能名称、类别、模板、变量、名称空间、点数和点数,除非明确指定为地方单位。

方案管理员的任务是确保每个名称空间、类别、功能等在所显示的每个翻译单位适当申报,所有提及同一实体的声明都是一致的。 [......]

In many cases there are errors that the C++ compiler is not required to catch. Many of them are for example errors that are impossible to detect by analyzing one translation unit at a time.

例如,如果你只是在主人档案中宣布,就没有用模板提出复杂的案件。

void foo(int x);

and then you provide two distinct definitions for the function in different translation units the C++ compiler is not required to give an error at link time.

Note that this is clearly not impossible to happen by mistake because indeed there could even be two distinct headers with a global function with the same signature and part of the project using one header and part of the project using the other.

如果你宣布某一类别<代码>,情况就相同。 Foo,有两种不同的主人档案,有不同的申报和不同的执行。

这种对点名的滥用只是一种不要求汇编者能够赶上的错误。





相关问题
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?