快乐地链接不兼容的类型导致混乱 [英] Happily linking incompatible types leads to chaos

查看:143
本文介绍了快乐地链接不兼容的类型导致混乱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图找出 g ++ 的一些边界,特别是链接(C ++)对象文件。我发现以下的好奇心,我尽量在要求之前压缩。

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

File 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 c $ c> g ++ -Wall -c b.cpp

File b.cpp compiled with g++ -Wall -c b.cpp

#include "common.h"

TMPL_Y('b',unsigned long long);

TMPL_Z(Zb);

TMPL_Z_impl('b',Zb);

文件 main.cpp g ++ -Wall ao bo 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

The result of ./a.out is

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



问题



现在, code> g ++ 给我一些讨厌的名字,试图链接 ao bo 在一起。特别是 za.y = zb.y 的赋值是邪恶的。不仅 g ++ 根本不抱怨,我想让它链接到同一名称的不兼容类型( Y ),但它完全忽略了 bo (分别 b.cpp )中的辅助定义。

Question

Now, I would have expected g++ to call me some nasty names for trying to link a.o and b.o together. Especially the assignment of za.y = zb.y is evil. Not only that g++ does not complain at all, that I want it to link together incompatible types with the same name (Y) but it completely ignores the secondary definition in b.o (resp. b.cpp).

我的意思是我没有做某事 sooo 。这是相当合理的两个编译单元可以使用相同的名称为本地类,尤其是。在一个大项目中。

I mean I'm not doing something sooo far fetched. It is quite reasonable that two compilation units could use the same name for local classes, esp. in a large project.

这是一个错误?

推荐答案

在你的例子中,你可以把Y的定义放在一个匿名命名空间这个:

In your example, you could put the definition of Y in an anonymous namespace like this:

#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,并且链接器将能够正确关联。

this essentially creates a unique namespace for each compilation unit and you have, in effect, unique Y's, and the linker will be able to associate correctly.

至于语句

za.y = zb.y;

这将仍然会产生不可预测的结果,因为2种类型不兼容。

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

这篇关于快乐地链接不兼容的类型导致混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆