简体   繁体   English

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

[英]Basic new/delete operator logging

I'd like to overload global and non-global new/delete operators for logging. 我想重载全局和非全局new / delete运算符以进行日志记录。

As I just want to add logging informations, I'd like to keep the standard behavior of this operators. 当我只想添加日志记录信息时,我想保留此运算符的标准行为。

Is there a way to overload new/delete operator to add logging but without having to rewrite the standard behavior (which might be error prone) ? 有没有一种方法可以使new / delete运算符超载以添加日志记录,而不必重写标准行为(可能容易出错)?

Actually, I not only need standard behavior. 实际上,我不仅需要标准行为。 I need the same behavior as Visual 2010 implementations, which might be not standard. 我需要与Visual 2010实现相同的行为,这可能不是标准的。

The kind of error I am looking for with this kind of logging is new[]/delete mismatch. 我正在用这种日志记录寻找的错误类型是new [] / delete mismatch。

I could use classic tools but they slowdown the execution and I'd like to share the binary with other people to gather more informations. 我可以使用经典工具,但是它们会降低执行速度,并且我想与其他人共享二进制文件以收集更多信息。

You can use malloc / free for the basic allocation. 您可以使用malloc / free进行基本分配。 Handling full standards compliance for new is a bit tricky; 处理new标准的完整标准有些棘手; you need something like: 您需要类似:

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

Often, however, you don't need such full compliance. 但是,通常,您不需要如此完全的合规性。 If you say that you don't support setting the new_handler , for example, you can simplify greatly. 例如,如果您说不支持设置new_handler ,则可以大大简化。 In the overloaded version I use for testing, in fact, if malloc really fails, I abort (but this version has options to trigger a failure of new , on demand, since I want to test that my code reacts correctly to it as well). 实际上,在我用于测试的重载版本中,如果malloc确实失败,我会中止(但是该版本具有按需触发new失败的选项,因为我也想测试我的代码也能正确响应) 。

If you're logging, be very careful to avoid endless recursion. 如果您正在记录日志,请非常小心,以避免无限递归。 The only functions guaranteed not to use operator new in the standard library are malloc and free . 保证不使用标准库中的operator new的唯一函数是mallocfree Of course, a lot have no reason to allocate dynamically, and I don't worry about functions like memcpy or strlen . 当然,很多人没有理由动态分配,而且我不必担心诸如memcpystrlen类的函数。 In practice, you are probably safe with any of the functions in the C library (although in theory, printf could be implemented in terms of iostream ). 实际上,使用C库中的任何函数都可能是安全的(尽管从理论上讲,可以使用iostream来实现printf )。 But any use of iostream, locale or the standard containers is out, unless you protect against recursion: 但是,除非可以防止递归,否则对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;
}

Formally, you should do the same for operator delete , although in practice, if you're logging to a file, I wouldn't expect any delete except in close() or the destructor. 正式地,您应该对operator delete进行相同的operator delete ,尽管在实践中,如果您要登录到文件,除了close()或析构函数之外,我不希望有任何delete

You can redefine the new keyword to call a different signature and pass __FILE__ and such. 您可以重新定义new关键字以调用其他签名并传递__FILE__等。

In the general case this works out OK. 在一般情况下,这可以解决。 When you start using objects that override operator new though you kinda screw yourself. 当您开始使用覆盖operator new对象时,虽然有点麻烦。

If I knew it by memory I'd share, but you can probably find with google. 如果我能通过记忆知道这一点,我会分享,但是您可能可以在Google上找到它。 I think there's an implementation on codeproject somewhere. 我认为在某个地方的codeproject上有一个实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM