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

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

 
阅读更多
最近写过一个连锁酒店预订的一个小程序。和本文相关的部分代码摘录下来说明本主题内容 。
如果连锁酒店系统是存储各个酒店的指针来管理的,那么我们一般都是希望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));
}





分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics