【问题标题】:Does this code violate One Definition Rule?此代码是否违反单一定义规则?
【发布时间】:2020-02-24 12:57:15
【问题描述】:

AOSP10 中的某些代码似乎违反了 ODR:

来源 1:

struct ExtentsParam
{
  void init (const OT::cff1::accelerator_t *_cff)
  {
    path_open = false;
    cff = _cff;
    bounds.init ();
  }
  void start_path ()         { path_open = true; }
  void end_path ()           { path_open = false; }
  bool is_path_open () const { return path_open; }
  bool    path_open;
  Bounds  bounds;
  const OT::cff1::accelerator_t *cff;
};

来自: https://android.googlesource.com/platform/external/harfbuzz_ng/+/refs/heads/android10-gsi/src/hb-ot-cff1-table.cc

来源 2:

struct ExtentsParam
{
  void init ()
  {
    path_open = false;
    min_x.set_int (0x7FFFFFFF);
    min_y.set_int (0x7FFFFFFF);
    max_x.set_int (-0x80000000);
    max_y.set_int (-0x80000000);
  }
  void start_path ()         { path_open = true; }
  void end_path ()           { path_open = false; }
  bool is_path_open () const { return path_open; }
  void update_bounds (const Point &pt)
  {
    if (pt.x < min_x) min_x = pt.x;
    if (pt.x > max_x) max_x = pt.x;
    if (pt.y < min_y) min_y = pt.y;
    if (pt.y > max_y) max_y = pt.y;
  }
  bool  path_open;
  Number min_x;
  Number min_y;
  Number max_x;
  Number max_y;
};

来自: https://android.googlesource.com/platform/external/harfbuzz_ng/+/refs/heads/android10-gsi/src/hb-ot-cff2-table.cc

构建脚本:

...
srcs: [
    ...
    "src/hb-ot-cff1-table.cc",
    "src/hb-ot-cff2-table.cc",
],
...

https://android.googlesource.com/platform/external/harfbuzz_ng/+/refs/heads/android10-gsi/Android.bp

这些源也内置在同一个共享库中。两个来源都有“struct ExtentsParam”的定义,内容完全不同。这两个结构似乎都只在本地使用。

这两个来源具有相似的名称,因此无意重复名称的可能性很低。在 Google 中违反 ODR 的可能性可能很低。

是吗?

【问题讨论】:

  • 在问题中输入代码而不是提供参考。
  • 使用 ODR,与其他格式不正确的程序 NDR(以及 UB)一样,事情可以“按预期工作”。所以在这些情况下很容易被忽视。
  • @Jarod42 是否有可能不违反 ODR?如果 ODR 可以存在于 Google 的代码中,那为什么构建系统很久以前不开始检查这些潜在的模式,而这并没有花费太多时间?
  • 根据您提供的部分信息,无法确定。假设两个源文件都被编译并链接到同一个程序中,并且 struct ExtentsParam 在同一个范围内(例如在同一个命名空间中),那么行为是未定义的,因为 struct 定义不包含同一组令牌。如果与此有差异(例如,两个 struct 定义位于不同的命名空间中),则行为可能是明确定义的。
  • @jw_ 这是个好问题。老实说,我希望静态分析器能够捕捉到这一点。

标签: c++ one-definition-rule


【解决方案1】:

是的:因为它们都在全局命名空间中,这绝对违反了 ODR。

仅在定义它们的翻译单元中使用的类类型没有例外;一个程序只能包含 一个 具有任何给定名称的类类型。

它符合豁免此规则的标准的首要要求:

[..] 类类型可以有多个定义[..] 在程序中,前提是每个定义出现在不同的翻译单元中,并且定义满足以下要求。 [..] 给定这样一个名为D 的实体在多个翻译单元中定义,应满足以下所有要求。 [..]D 的每个定义都应包含相同的标记序列 [..] (ref)

开发人员只是“很幸运”,因为链接器没有尝试做任何导致此违规行为症状的滑稽动作。

这就是命名空间的用途。例如,如果类类型仅在定义它的翻译单元中使用,它可能已在匿名命名空间中定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    相关资源
    最近更新 更多