簡體   English   中英

全局重載運算符 new/new[] delete/delete[] C++

[英]overload operators new/new[] delete/delete[] globally C++

我有這個用於重載運算符 new 和 delete 的示例代碼

#include <iostream>
#include <cstddef>
#include <new>

#ifdef USE_ZMALLOC
extern "C" {
#include "zmalloc.h"
}
#define m_malloc zmalloc
#define m_free zfree
#else
#ifdef USE_JEMALLOC
#include <jemalloc/jemalloc.h>
#define m_malloc je_malloc
#define m_free je_free
#else
#include "malloc.h"
#define m_malloc std::malloc
#define m_free std::free
#endif
#endif

// C++ requires that operator new return a legitimate pointer
//  even when zero bytes are requested. That's why if (size == 0) size = 1
void* operator new (std::size_t size) throw (std::bad_alloc) {
  using namespace std;
  if (size == 0) { // Handle 0-byte requests by treating them as 1-byte requests
    size = 1;
  }

  while (true) {
    void* mem = m_malloc(size);

    if (mem != nullptr) {
      return mem;
    } 

    new_handler global_handler = set_new_handler(nullptr);
    set_new_handler(global_handler);

    if (global_handler) {
      (*global_handler)();
    } else {
      throw bad_alloc();
    }

  }
}

void* operator new[] (std::size_t size) throw (std::bad_alloc) {
  return operator new(size);
}

void operator delete (void* ptr) throw() {
  if (ptr == nullptr) {
    return;
  }

  m_free(ptr);
}

void operator delete[] (void* ptr) throw() {
  operator delete(ptr);
}

這段代碼實際上是有效的,一切似乎都是正確的。 我的問題是:使用 valgrind 時,如果我這樣做:

int main() {
  Foo** foo = new Foo*[10];

  std::cout << "# " << zmalloc_used_memory() << "." << std::endl;

  delete foo;  // Using wrong delete operator

  return 0;
}

valgrind 不會抱怨使用了錯誤的操作符 delete。 如果我使用默認的操作符 new/delete 對,valgrind 會警告我操作符刪除錯誤。

1)我的新/刪除操作員有問題嗎?
2) valgrind 不再警告此類錯誤是否正常?

謝謝!

首先,這些不是重載(因為它們具有完全相同的原型)。 這些是替代品。

最有可能的問題是 Valgrind 不知道您已經替換了這些全局運算符。 如果您在共享庫中進行替換,Valgrind 將看到函數和原型,並且能夠掛鈎它們。 但是,如果替換是在您的可執行文件本身中,您需要告訴 Valgrind。 我認為這可以通過檢測代碼來實現,但這非常困難。 更簡單的方法是使用 Valgrind 選項 --soname-synonyms=somalloc=NONE 。

更新:我不確定 OP 使用的是哪個版本的 Valgrind,但自 Valgrind 3.12.0(2016 年 10 月 20 日)以來,您不需要任何選項來檢測用戶更換 malloc/new。

我使用 Valgrind 3.20.0(來自 git HEAD,2022 年 6 月)得到的輸出是

==5989== Mismatched free() / delete / delete []
==5989==    at 0x4030741: operator delete(void*, unsigned long) (vg_replace_malloc.c:947)
==5989==    by 0x4012D9: main (in /home/pafloyd/scratch/vg_examples/so_replace_new/srn)
==5989==  Address 0x5328c80 is 0 bytes inside a block of size 80 alloc'd
==5989==    at 0x402F103: operator new[](unsigned long) (vg_replace_malloc.c:652)
==5989==    by 0x4012BF: main (in /home/pafloyd/scratch/vg_examples/so_replace_new/srn)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM