C++中类的数据成员的安全隐患
作者:周云才
(江汉石油学院计算机科学系 邮编 4340023)
在任何一本关于"C++语言程序设计"的书中都有类似于如下的描述:
在一个类中,C++用三个关键词设置访问界限:public, private和protected。它们决定了跟在他们后面的标识符的被使用情况:public意味着其后的标识符可以被用户定义的其实例引用;而private则说明其后的标识符除了类的成员函数之外,用户定义的其实例不能引用;protected为类的继承提供了接口,同时保护其不被外界访问。
事实上也,如果要想利用类的一个对象(或实例)来访问其成员时确实如此。但是,在C++中,由于容许将指针类型进行任意转换,从而给用户提供了一个"穿越保护屏障"的方法。这可以从以下的例程中看到:
#include
class CMyClass{
double d;
int x,y;
const char ch;
public:
int z;
CMyClass(int xx,int yy,char c):ch(c){x=xx,y=yy;d=9.8759;z=0;}
void Show(){
cout<<"d="<<d<<" "<<"x="<<x<<" "<<"y="<<y<<" "<<"ch="<<ch<<" ";
cout<<"z="<<z<<endl; }
};
void main()
{
cout<<sizeof(CMyClass)<<endl;
CMyClass p(1,2,''U'');
p.Show();
CMyClass *ptr=&p;
// ptr->x=9.32145; //错误,因为x是其私有成员,外部不能直接访问。
double*dP=(double*)ptr; //获取了p.d的地址
*dP=9.32145; //修改p.d的值
int*iP=(int*)(dP+1); //获取了p.x的地址
*iP=300; //修改p.x的值
*(iP+1)=200; //修改p.y的值
*(iP+2)=65; //修改ch的值变为''A'',但ch是常数!
*(iP+3)=100; //修改p.z的值
p.Show();
}
运行结果如下:
**********************************************
24
d=9.8759 x=1 y=2 ch=U z=0
d=9.32145 x=300 y=200 ch=A z=100
**********************************************
类CMyClass中有四个私有成员double d、int x,y与const char ch,通过其对象p肯定是不能察看或修改其值的,但是利用指向对象p的指针ptr我们做到了。利用将ptr转换成double* dP修改了d的值,然后再将dP转化成int*iP修改了其余所有数据成员的值。从以上的结果还看出char在类中占有与int相同大小的内存,这是因为类的alignment(边缘调整)引起的。一个更糟糕的事情是ch的值也被修改了!它可是一个const!!pointer is a god!它真是无所不能!!
指针的"不安全"性在此例中得到了充分的展示,应该对它进行限制!
分享到:
相关推荐
3. 使用友元函数(非成员函数)比友元类更安全,因为友元函数没有自己的数据成员,不会意外地改变对象状态。 4. 友元关系是非继承的,这意味着子类不会自动成为父类的友元。 总的来说,友元类是C++中的一种强大工具...
在C++编程语言中,友元机制是一种特殊的设计策略,用于打破封装的限制,允许类之间或函数与类之间的非成员访问。这种机制虽然提供了更大的灵活性,但也可能削弱类的封装性和安全性。以下是对友元类和友元函数的详细...
C++编程语言在软件开发中占据着重要地位,然而,由于其灵活性,也常常伴随着安全隐患和漏洞。"BoundCheck"是一种专门针对这类问题的工具,它适用于多种开发环境,包括Visual C++和Delphi,旨在帮助开发者检测并修复...
此外,使用宏定义(`#define`)也是定义常量的一种常见方法,但在现代C++编程中更推荐使用`constexpr`来定义编译时常量,因为这种方式提供了更多的类型安全检查。 #### 2. 初始化和类型转换 ##### 2.1 声明、定义...
- 操作:std::string提供了丰富的成员函数,如append、compare、copy、find、insert、erase等,可以方便地进行字符串操作,避免了C风格字符串的安全隐患。 - 动态大小调整:std::string会自动管理内存,可以动态...
【C++编程思想006】章节主要讨论的是C++中的输入输出流(Input/Output Streams)的概念,这是C++中处理I/O操作的一种高效、安全的方法,旨在提供统一的接口,简化对不同类型的输入输出源(如标准输入输出、文件、...
书中强调了内存管理和字符操作的安全性,特别提到了像`strncopy`和`fscanf`这类函数在使用时可能存在安全隐患。 1. **内存管理**:在C++中,程序员需要手动管理内存,这既是其强大之处,也是潜在问题的来源。理解...
6. 不能重载的运算符:在C++中,某些运算符不能被重载,比如`::`(作用域解析运算符),它是用来访问命名空间或类中的成员,具有特殊含义,因此不能像其他运算符那样被用户定义新的行为。选项A正确,它不能被重载以...
运行时类型识别(RTTI)和类型转换紧密相关,但C++中这些机制的实现并非总是直观或安全。 ##### 3.15 新类型转换 为了改进原有的类型转换机制,C++引入了新的类型转换操作符,但这并没有完全解决原有的问题。 ##### ...
在C++编程语言中,`friend`函数是一个特殊类型的函数,它可以访问类的私有和保护成员,即使这些成员在通常情况下是不可见的。`friend`函数的概念是为了在特定情况下打破封装,以便提高代码效率或者实现特定的功能,...
例如,成员函数和数据成员默认为公有的,这限制了封装的有效性,增加了维护成本。 ##### 缺乏二进制规范 没有明确的二进制接口规范意味着编译器之间很难保证二进制兼容性,这对于跨平台开发尤其不利。 ##### 缺少...