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

最近写过一个连锁酒店预订的一个小程序。和本文相关的部分代码摘录下来说明本主题内容 。
如果连锁酒店系统是存储各个酒店的指针来管理的,那么我们一般都是希望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 = new Hotel("Lakewood", "Miami", 100, rate3);
    Hotel* pBridgewood = new Hotel("Bridgewood", "Miami", 100, rate4);
    Hotel* pRidgewood = new Hotel("Ridgewood", "Miami", 100, rate5);

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

    /*
    //-----------------------------------------
    // Test allocate the hotel object on stack
    //-----------------------------------------
    Hotel Lakewood("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);
    */

这里的代码仅仅运行在Windows上,调用了Windows的系统函数来获取内存地址信息。
#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);
    
private:
    bool isObjectOnStack(Hotel* pHotel);

    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));
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值