2

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

由于我只想添加日志信息,因此我想保留此操作员的标准行为。

有没有办法重载 new/delete 运算符来添加日志记录,但不必重写标准行为(这可能容易出错)?

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

我在这种日志记录中寻找的错误类型是 new[]/delete mismatch。

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

4

2 回答 2

4

您可以使用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标准库中使用的函数是mallocfree。当然,很多没有理由动态分配,我也不担心memcpyor 之类的函数strlen。在实践中,您可能对 C 库中的任何函数都是安全的(尽管理论上printf可以根据iostream. 但是,除非您防止递归,否则任何使用 iostream、语言环境或标准容器的方法都已失效:

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 ,您应该为close().

于 2012-09-13T09:49:09.457 回答
0

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

在一般情况下,这可以正常工作。当您开始使用覆盖的对象时,operator new尽管您有点自欺欺人。

如果我是凭记忆知道的,我会分享,但您可能可以通过 google 找到。我认为在某个地方的 codeproject 上有一个实现。

于 2012-09-13T09:39:49.877 回答