`
runfeel
  • 浏览: 935620 次
文章分类
社区版块
存档分类
最新评论

为了保证系统安全性,请在析构函数中检查对象指针是否是在栈上申请

 
阅读更多
最近写过一个连锁酒店预订的一个小程序。和本文相关的部分代码摘录下来说明本主题内容 。
如果连锁酒店系统是存储各个酒店的指针来管理的,那么我们一般都是希望new出一个酒店并且添加到连锁系统的酒店对象指针的容器中(本文中的容器是map)。那么你是否能保证添加的指针一定是在堆上申请的呢?似乎这不是连锁系统自身可以控制的。那么如果传入的是栈指针,而在连锁系统对象析构时,把它存储的酒店对象指针当成堆指针delete的时候,我们的系统一定就崩溃了。
因此,如果你不能严格限制糟糕的程序员给你传入栈指针,那么你可以判断他传入指针的类型,来灵活应对。

对于编写库函数的同学,这一点需要特别注意,有时候我们往往无法控制程序员传入的数据类型,所以你不能假设他一定是按照你设想的方式和类型处理,我们能做的是尽可能的屏蔽或者处理这样的情况。

实例,请看代码(代码并不完整,仅仅为了说明本问题),注意红色字体的函数。

HotelManagement MiamiHotels;
//Hotel price according rate
HotelRate rate3(110.0, 90.0, 80.0, 80.0);
HotelRate rate4(160.0, 60.0, 110.0, 50.0);
HotelRate rate5(220.0, 150.0, 100.0, 40.0);

Hotel* pLakewood =newHotel("Lakewood", "Miami", 100, rate3);
Hotel* pBridgewood =newHotel("Bridgewood", "Miami", 100, rate4);
Hotel* pRidgewood =newHotel("Ridgewood", "Miami", 100, rate5);

MiamiHotels.addHotelToManage(pLakewood);
MiamiHotels.addHotelToManage(pBridgewood);
MiamiHotels.addHotelToManage(pRidgewood);

/*
//-----------------------------------------
// Test allocate the hotel object on stack
//-----------------------------------------
HotelLakewood("Lakewood", "Miami", 100, rate3);
Hotel Bridgewood("Bridgewood", "Miami", 100, rate4);
Hotel Ridgewood("Ridgewood", "Miami", 100, rate5);
MiamiHotels.addHotelToManage(&Lakewood);
MiamiHotels.addHotelToManage(&Bridgewood);
MiamiHotels.addHotelToManage(&Ridgewood);
*/



#define HOTEL_MANAGEMENT_H

#include <windows.h>
#include <iostream>
#include <map>
#include <string>
#include "Hotel.h"

using namespace std;

class HotelManagement
{
public:
typedef map<string,Hotel*>::iterator hotels_iter;

~HotelManagement();
void addHotelToManage(Hotel* pHotel);
bool isHotelMapEmpty();
bool findThecheapestHotel(int weekdays, int weekends, bool isRewardsCustomer, string& hotelName);
boolisObjectOnStack(Hotel* pHotel);

private:
map<string, Hotel*> _HotelsMap;
};

#endif



#include "HotelManagement.h"

bool HotelManagement::isObjectOnStack(Hotel* pHotel)
{
int stackValue = 0;
MEMORY_BASIC_INFORMATION mi = {0};

DWORD dwRet = VirtualQuery(&stackValue, &mi, sizeof(mi));

if(dwRet > 0)
{
return pHotel >= mi.BaseAddress
&& (DWORD)pHotel < (DWORD)mi.BaseAddress + mi.RegionSize;
}

return false;
}

HotelManagement::~HotelManagement()
{
hotels_iter iter;
for(iter = this->_HotelsMap.begin(); iter != this->_HotelsMap.end(); iter++)
{
if(isObjectOnStack(iter->second))
{
continue;
}

if(iter->second != NULL)
{
Hotel* temp = iter->second;
iter->second = NULL;
delete temp;
}
}
this->_HotelsMap.clear();
}

void HotelManagement::addHotelToManage(Hotel* pHotel)
{
_HotelsMap.insert(std::make_pair(pHotel->getHotelName(), pHotel));
}





分享到:
评论

相关推荐

    c++经典面试题及答案.docx

    - 析构函数是类的一个特殊成员函数,用于在对象生命周期结束时(例如对象离开其作用域或被delete)清理资源。它没有返回值且名称前有波浪线~。 - 虚函数(virtual)用于实现多态性,允许子类覆盖基类的函数,使得...

    c,c++面试题.pdf

    - 析构函数:在对象生命周期结束时(如对象离开作用域或delete时)自动调用,用于释放对象在构造时分配的资源。 - 虚函数:使用virtual关键字声明,允许子类重写基类的行为,实现多态性。在派生类对象通过基类指针...

    C++基础面试题.docx

    析构函数是C++中的特殊成员函数,用于在对象生命周期结束时释放资源。它无返回值,无参数,名字与类名相同,由系统自动调用。虚函数在继承体系中起到关键作用,当基类的函数在派生类中需要重定义时,声明为虚函数,...

    CC++电话面试

    - 如果没有虚析构函数,那么在使用基类指针删除派生类对象时,只会调用基类的析构函数,这可能会导致资源泄露或其他问题。 #### 20. TCP/IP协议简介? - **TCP/IP协议**: - 是Internet的基础协议之一,用于实现...

    嵌入式面试技术问题汇总_嵌入式-常用知识&面试题库_大厂面试真题.docx

    虚析构函数是一种特殊的析构函数,用于释放对象的资源。 36. 进程和线程的区别? 进程和线程都是并发执行的单位,但是它们有着不同的特点: * 进程:进程是一个独立的执行单元,拥有独立的地址空间。 * 线程:...

    百度一面1

    - 虚析构函数允许在继承层次结构中正确地销毁对象。 15. **静态库与动态库**: - 静态库在编译时合并到目标代码中,程序体积大但无需运行时依赖。 - 动态库在运行时加载,节省磁盘空间,但需要对应的库文件。 ...

    IT常见面试笔试题含答案

    4. **析构函数**:释放对象占用的资源。 **代码实现**: ```c++ class String { public: String(const char* str = NULL); String(const String& other); ~String(); String& operator=(const String& other); ...

    .net笔试题及答案

    **问题**: `swtich` 是否能作用在 `byte` 上,是否能作用在 `long` 上,是否能作用在 `String` 上? **解答**: 在 C# 中,`switch` 语句中的表达式可以是 `int`, `char`, `enum` 或者 `string` 类型。因此,它确实...

Global site tag (gtag.js) - Google Analytics