使用公共成员变量的地址访问私有成员

Posted

技术标签:

【中文标题】使用公共成员变量的地址访问私有成员【英文标题】:Using the address of a public member variable to access a private member 【发布时间】:2016-06-23 03:02:03 【问题描述】:

我创建了以下简单的测试程序来证明我可以使用公共整数的地址来访问私有整数的值:

#include <iostream>
using namespace std;
class CarType
  public:
    int year;
    CarType(int price, int year)this -> year = year; this -> price = price;;
  private: 
    int price;
;

int main()
  //Create new CarType object
  CarType a = CarType(15000, 1999);
  //Increment the memory address of public member variable, year by 1 and save the result
  int* pricePointer = &a.year+1;
  //De-reference the memory address and output it
  cout << "PRICE: "<< *pricePointer << endl;
  return 0;

输出显示我可以通过知道年份的地址来访问价格变量。有没有办法防止这种情况发生?这只是一种边缘情况还是适用于所有类型的对象?

【问题讨论】:

C++ 不会阻止有人朝自己的脚开枪。 没有没有保证你正在做的事情总是有效的。本质上,在这种情况下,编译器以这样一种方式布置内存,即变量price 被放置在“紧随”year 之后。但是因为您使用的是类而不是 POD,并且编译器确实向对象“添加了东西”,所以不能保证内存总是以这种方式布局。尝试添加其他成员变量和方法,看看会发生什么。有关详细信息,请参阅 Stephen C. Dewhurst 的 C++ Common Knowledge 的第 11 条。其他更熟悉编译器设计的人可能能够提供更多详细信息。 【参考方案1】:

这是可能未定义的(但肯定是不明智的)行为,您可以通过与防止人们写入随机地址或防止没有经验的人用电锯切断四肢的方式大致相同的方式来防止它。换句话说,根本没有。

警告编码器。

我在上面的段落中说可能的原因是它并不完全清楚。在语言律师术语中,请参阅C++14 5.7 Additive operators /4

对于这些运算符,指向非数组对象的指针与指向长度为 1 的数组的第一个元素的指针的行为相同,该数组的元素类型为对象的类型。

/5 在讨论向指针添加整数值时:

如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则计算不应产生溢出;否则,行为未定义。

在您的情况下,您的指针实际上指向“最后一个元素之后”,因此添加本身不会产生未定义的行为。

您可能认为取消引用该对象是未定义的,但根据 3.9.2 Compound types /3 中的注释,它似乎是有效的:

例如,数组末尾的地址 (5.7) 将被视为指向可能位于该地址的数组元素类型的不相关对象。

但是,无论是否未定义,取消引用仍然是不明智的,因为您实际上并不知道那里有一个正确类型的变量。实现可以随意填充结构,因此无法保证price*(year + 1) 相同。

【讨论】:

如果我可以访问我正在实施的库的源代码,这会是一个安全问题吗? (例如,写得不好的密码验证函数) @isquaredr Is Encapsulation a security device? @isquaredr 如果您没有access to the source-code of the library I was implementing ;-) 我认为您需要详细说明什么是“安全问题 i>”你可能会担心。 @PaulMcKenzie 这是一个很好的观点,正是我想要的。根据讲座,我了解到private 是一种保护数据的方式。 @isquaredr, private 是一种保护来自开发人员的数据的方法,该方法遵循规则并且有效,尝试访问私有成员将拒绝编译的事实证明了这一点。它不能防止围绕这种保护的终端运行。你总是可以这样做,但结果是:它可能会也可能不会。

以上是关于使用公共成员变量的地址访问私有成员的主要内容,如果未能解决你的问题,请参考以下文章

如何对类中的私有成员变量进行赋值和访问

关于何时在私有成员变量上实现访问器而不是将它们公开的实践

私有静态变量

子类真的继承私有成员变量吗?

Java子类访问父类的私有成员变量

公共类,但私有成员变量? [复制]