【问题标题】:May pointer to members circumvent the access level of a member?指向成员的指针可以绕过成员的访问级别吗?
【发布时间】:2012-04-12 00:49:41
【问题描述】:

我们臭名昭著的 litb 在how to circumvent the access check 上有一篇有趣的文章。

这个简单的代码就充分展示了:

#include <iostream>

template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};

// use
struct A {
  A(int a):a(a) { }
private:
  int a;
};

// tag used to access A::a
struct A_f { 
  typedef int A::*type;
  friend type get(A_f);
};

template struct Rob<A_f, &A::a>;

int main() {
  A a(42);
  std::cout << "proof: " << a.*get(A_f()) << std::endl;
}

使用gcc 4.3.4gcc 4.5.1、gcc 4.7.0(请参阅 user1131467 的评论)编译和运行(输出 42)并在 C+ 中使用 Clang 3.0 和 Comeau C/C++ 4.3.10.1 编译+03 严格模式和 MSVC 2005。

Luchian 在this answer 上问我,我用它来证明它实际上是合法的。我同意 Luchian 的说法,这很奇怪,但是 Clang 和 Comeau 都是可用的最“标准”编译器的有力竞争者(默认情况下比 MSVC 更多)...

我在可用的标准草案中找不到任何内容(n3337 是我得到的最后一个版本)。

那么...任何人都可以证明它合法与否吗?

【问题讨论】:

  • 仅供参考,这会在 -std=c++11-std=gnu++11 中输出 proof:42g++-4.7 (Debian 4.7.0-1) 4.7.0
  • 对不起,这是我的错。这确实编译,没有编译的是stackoverflow.com/a/6886432/673730 - 我试图访问一个私有函数,而不是数据成员。
  • 顺便说一句,我仍在寻找答案,如果答案有效,那将正是我一直在寻找的,但事实并非如此。
  • @LuchianGrigore:没问题,感谢您纠正问题。
  • @user1131467:感谢测试。

标签: c++ c++11 standards-compliance


【解决方案1】:

代码显然是非法的(并且需要编译时诊断)。 行内:

template struct Rob<A_f, &A::a>;

表达式A::a 访问A 的私​​有成员。

标准对此非常明确:“应用访问控制 统一到所有名称,无论名称是否来自 声明或表达。”(第 11/4 节,已添加重点)。由于aA 中的私有名称,因此在A 之外对其的任何引用都是非法的。

【讨论】:

  • 其实并不违法,后面为显式模板实例化添加了一个异常。那里的“全部”显然具有误导性,它是“全部,除非另有说明”。我不会投反对票,因为这很不直观。
  • @GManNickG 实际上,还不清楚,我认为 DR 是合适的。在标准中,“all”表示“全部”,而不是“全部,除非另有说明”,第 14.7.2 节中的上下文可以允许其他解释(尽管它们不是很自然)。这看起来很矛盾,这意味着 DR 是有序的。
  • 你是对的,没有必要有那个资格。
  • 虽然您在规范中指出这一矛盾是正确的(IMO),但这并不意味着“代码显然是非法的。”。这意味着,就像任何严肃的法律术语一样,“如果该法律的任何规则被证明是有缺陷或非法的,它将被尽可能符合预期目的的规则所取代。” (可分割性条款)。你不能接受一个规则,并基于一个矛盾来解释它与委员会的意图相矛盾。
  • 您也可以遍历 wg21 的 current-issues 页面的问题并从字面上拒绝 any 程序,因为没有对标准中的缺陷规则进行合理的修复。
【解决方案2】:

是的,这是合法的。相关文本在第 14.7.2/12 节,讨论显式模板实例化:

12 通常的访问检查规则不适用于用于指定显式实例化的名称。 [ 注意:特别是,在函数声明器中使用的模板参数和名称(包括参数类型、返回类型和异常规范)可能是通常无法访问的私有类型或对象,并且模板可能是成员模板或成员函数,通常不会 无障碍。 — 尾注 ]

强调我的。

【讨论】:

  • 啊!这可能是我最喜欢标准的地方,要对某事有一个全面的看法,你只需要跋涉整个事情并将各个部分拼凑起来。
  • @MatthieuM.:但这也是我讨厌标准的原因! :) 编辑:嗖!
  • 这本来是讽刺的 ;) 虽然现在它在 github 上,但也许我们可以建议编辑以交叉链接 James 引用的这一段!
  • @MatthieuM.:啊,是的,我忘记了那个变化。 ......我会让你做的。我可能只会让自己难堪。
  • @mat 哦,不错。你碰巧知道github url吗?
猜你喜欢
  • 1970-01-01
  • 2014-02-19
  • 2013-05-02
  • 1970-01-01
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多