删除静态指针指向的动态内存

时间:2013-05-05 10:48:38

标签: c++ windows memory-management kernel device-driver

我有以下结构(简化):

class myType
{
    static char* data;
    //more private data here
public:
    //public interface here
};

datamyType的所有实例之间共享的资源,它指向动态分配的内存(在初始化时由其中一个实例分配)。

到目前为止一切顺利。当我需要释放data指向的内存时,问题就出现了。引用计数在这里不是一个解决方案,因为在某个执行点没有myType的单个实例是有效且可能的情况 - 以后可以创建一个新实例 - 因此data必须持续。

我需要在驱动程序卸载时释放该内存,但卸载与myType对象的实际销毁无关,因此我不得不手动释放data。这是可以接受的,但data是(并且应该是)private并且从卸载处理程序中无法访问。当然,我可以在static内创建publicdestroy myType功能,但这似乎不对 - 毕竟我不需要public初始化器,为什么我需要一个释放内存?不应该从外部myType实例访问该数据。

我会很感激有关这个问题的任何见解。

3 个答案:

答案 0 :(得分:3)

根据代码的复杂程度,我更喜欢以下两个选项之一:

  1. 有一个静态公共destroyMetadata方法,如果在执行期间创建了任何实例,则需要调用该方法。就个人而言,我没有看到任何特别糟糕的方法来破坏隐含创建的数据。这种方法的问题只是它是一种手动方法,因此有点bugprone
  2. 创建一个(单例)卸载处理程序,您可以在其中注册要在清理时执行的回调。然后,您可以使destroyMetadata成为私有静态方法,并在首次创建data时将其注册到处理程序。这需要更多努力,但整体设计更清晰。
  3. 这两个中的哪一个适合您取决于您​​的清理可能变得多么复杂。如果你有几十个带有自定义清理的类,那么第二个选项似乎更可取,因为它可以产生更好的封装和更整洁的代码。但是,如果这是你的代码的唯一部分,你需要进行这样的清理,那么编写这样的通用处理程序(YAGNI)有点过分,所以第一种方法虽然在概念上更加混乱,但在这种情况下看起来要好得多。

答案 1 :(得分:1)

不需要公共初始化程序来分配它与释放它无关 - 在首次使用时分配它是微不足道的,因为你运行的代码知道它需要在那里(if(data == NULL)数据) = new ...),但是如果你的析构函数中没有意义,那么如果你想确保返回内存,则可能需要公共解除分配器。

另一种可能性(如果在您的情况下有意义)是在构造函数中递增的引用计数并在析构函数中递减但是当计数达到零时,不要立即取消分配。相反,那时你可以设置一个计时器在一定的“冷却”期后解除分配。如果在此计时器触发之前调用构造函数(或懒惰分配内存的其他代码),则取消计时器而不是重新分配,但如果计时器触发,则取消分配。

答案 2 :(得分:1)

我不明白为什么public static销毁功能看起来不对。当你争论自己时,所需的破坏时刻与对象及其实例本身的生命周期之间没有任何关系。因此,您负责与外部实体及时销毁,然后在逻辑上需要能够访问它。在这种情况下,public static方法最有意义。这种方式有点像垃圾收集器。

我认为底层架构存在缺陷,因为它需要您做出此决定,并且数据容器应该是一个单独的正确引用计数类,具有适当的生命周期控制和真正的垃圾收集器,但这取决于其余的码。所描述的解决方案可能是最好的。