基本的新建/删除操作员日志记录

Basic new/delete operator logging

本文关键字:操作员 日志 记录 删除 新建      更新时间:2023-10-16

我想重载全局和非全局的new/delete运算符以进行日志记录。

由于我只是想添加日志信息,所以我希望保留这些操作符的标准行为。

有没有一种方法可以重载新的/delete操作符来添加日志记录,但不必重写标准行为(这可能很容易出错)?

事实上,我不仅需要规范的行为。我需要与Visual 2010实现相同的行为,这可能不是标准的。

我在这种日志记录中寻找的错误类型是新的[]/delete不匹配。

我可以使用经典的工具,但它们会减慢执行速度,我想与其他人分享二进制文件以收集更多信息。

您可以使用malloc/free进行基本分配。处理已满new的标准遵从性有点棘手;你需要这样的东西:

void*
operator new( size_t n )
{
    void* results = malloc( n );
    while ( results == NULL ) {
        if ( std::get_new_handler() == NULL ) {
            throw std::bad_alloc();
        }
        (*std::get_new_handler())();
        results = malloc( n );
    }
    return results;
}

然而,通常情况下,您并不需要完全遵守。如果你这么说例如,您不支持设置new_handler,您可以大大简化。事实上,在我用于测试的重载版本中,如果malloc真的失败了,我会中止(但这个版本有选项根据需要触发new的失败,因为我想测试我的代码对它的反应也正确)。

如果您正在进行日志记录,请非常小心,避免无休止的递归。唯一保证不在标准库中使用operator new的函数分别为CCD_ 8和CCD_。当然,很多人没有理由分配动态,并且我不担心像memcpy或CCD_ 11。在实践中,使用任何函数都可能是安全的在C库中(尽管理论上printf可以在iostream的术语)。但是iostream、locale或标准的任何使用容器已用完,除非您防止递归:

void*
operator new( size_t n )
{
    static int recursionCount = 0;
    ++ recursionCount;
    void* results = malloc() ;
    //  Any additional logic you need...
    if ( recursionCount == 1 ) {
        logAllocation( results, n );
    }
    -- recursionCount;
    return results;
}

从形式上讲,您应该对operator delete执行同样的操作,尽管在练习一下,如果你登录到一个文件,我不希望有任何delete除了在CCD_ 16或析构函数中。

您可以重新定义new关键字以调用不同的签名并传递__FILE__等。

在一般情况下,这是可以的。当你开始使用覆盖operator new的对象时,尽管你有点搞砸了自己。

如果我凭记忆知道的话,我会分享,但你可能可以在谷歌上找到。我认为某个地方有一个代码项目的实现。