有效的使用和设计COM智能指针——条款14:有意识的限制智能指针的生命周期

本文通过实例讲解了在C++编程中如何正确管理智能指针的生命周期,避免因生命周期不当而导致的程序崩溃问题。建议使用作用域限定智能指针生命周期,并提供两种有效实践方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

条款14:有意识的限制智能指针的生命周期

更多条款请前往原文出处:http://blog.youkuaiyun.com/liuchang5

我们看一看下面这个例子会发生什么:

int main()
{
    hrRetCode = CoInitialize(NULL);
    KG_COM_ASSERT_EXIT(hrRetCode);
    CComPtr<IHello>  spHello = NULL;
    spHello.CoCreateInstance( CLSID_HELLO );
    KG_ASSERT_EXIT(spHello);
    ...
    Exit0:
    CoUninitialize();
    return 0;
}//运行结束后会崩溃


上面程序崩溃了。原因是没有限制智能指针的生命周期,CoUninitialize执行之后main函数才返回,此时智能指针出栈自动调用COM接口的Release方法。于是程序崩溃了~

正确的方法是将智能指针限定到某个特殊的栈空间中去,或者提前进行=NULL操作使其释放。而我更推荐于前者,因为他能保证即便是在异常情况下你的资源也会被正确的释放:

int main()
{
    hrRetCode = CoInitialize(NULL);
    KG_COM_ASSERT_EXIT(hrRetCode);
    {   //使用一个scope限制智能指针的声明周期
        CComPtr<IHello>  spHello = NULL;
        spHello.CoCreateInstance( CLSID_HELLO );
        KG_ASSERT_EXIT(spHello);
        ...
    }
    Exit0:
    CoUninitialize();
    return 0;
}


如果你觉得使用这种scope的方式不好看,那你也同样可以将所需使用的智能指针放到一个函数中去。并通过一个函数名标示清楚这段代码的大概意图。

再看一下下面这个例子,这个例子在前面的章节中出现过,但它还不理想。因为我们发现g_myStack是放在全局作用域中的。如果进行类似如下的操作则程序会崩溃。

    MyStack<CComPtr<ICalculator>> g_myStack(1000); //全局作用域中的智能指针作用
                                                   //域大于CoInitialize到CoUninitialize
    void func()
    {
        for (int i=0; i<500; i++)
        {
            CComPtr<ICalculator> spCalculator = NULL;
            spCalculator.CoCreateInstance(CLSID_CALCULATOR); 
            g_myStack.push(spCalculator);
        }   
    ...
        for (int i=0; i<100; i++)   //完成操作后MyStack中还存在400个资源
        {
            CComPtr<ICalculator> spCalculator = g_myStack.pop();
            spCalculator->DoSomething();
        }
    }

    int main()
    {
        hrRetCode = CoInitialize(NULL);
        KG_COM_ASSERT_EXIT(hrRetCode);
	func();
        Exit0:
        CoUninitialize();
        return 0;
    }      //别指望智能指针类会帮你处理好多余的资源,程序在这里直接崩溃了。


解决的办法根据情况而定:

1.如果你确实希望 g_myStack在全局上,那么你必须要有有效的代码保证其在程序运行完之前g_myStack为空,而不去依赖智能指针为你释放掉这部分资源。那么在CoUninitiallize执行前,准备一个特定的函数清理所使用的资源。即便没有相应的函数对资源进行处理,也至少用一个断言来尽可能早的发现这种情况。

2.否则呢?若你有办法减小g_myStack的作用域。那就尽可能的将他限制到一个栈空间上。当然这个栈空间的作用域是要小于CoInitialize与CoUninitialize间的作用域的。

这一节结束了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值