我有这个重载 operator 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 不会提示使用了错误的删除运算符。 如果我使用默认的 operator new/delete 对,valgrind 会警告我有关 operator delete 的错误。
1) 我的新/删除运算符有问题吗?
2) valgrind 不再警告此类错误是否正常?
谢谢!
最佳答案
首先,这些不是重载(因为它们具有完全相同的原型(prototype))。这些是替代品。
问题很可能是 Valgrind 不知道您已经替换了这些全局运算符。如果您在共享库中进行替换,Valgrind 将看到函数和原型(prototype)并将能够 Hook 它们。但是,如果替换是在您的可执行文件本身中,您将需要告诉 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)
关于c++ - 全局重载运算符 new/new[] delete/delete[] C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43990978/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我明白了:x,(y,z)=1,*[2,3]x#=>1y#=>2z#=>nil我想知道为什么z的值为nil。 最佳答案 x,(y,z)=1,*[2,3]右侧的splat*是内联扩展的,所以它等同于:x,(y,z)=1,2,3左边带括号的列表被视为嵌套赋值,所以它等价于:x=1y,z=23被丢弃,而z被分配给nil。 关于ruby-带括号和splat运算符的并行赋值,我们在StackOverflow上找到一个类似的问题: https://stackoverflow
我有一个gem,它有一个根据Rails.env的不同行为的方法:defself.envifdefined?(Rails)Rails.envelsif...现在我想编写一个规范来测试这个代码路径。目前我是这样做的:Kernel.const_set(:Rails,nil)Rails.should_receive(:env).and_return('production')...没关系,只是感觉很丑。另一种方法是在spec_helper中声明:moduleRails;end而且效果也很好。但也许有更好的方法?理想情况下,这应该有效:rails=double('Rails')rails.sho
我正在尝试将$stdout设置为临时写入一个文件,然后返回到一个文件。test.rb:old_stdout=$stdout$stdout.reopen("mytestfile.out",'w+')puts"thisgoesinmytestfile"$stdout=old_stdoutputs"thisshouldbeontheconsole"$stdout.reopen("mytestfile1.out",'w+')puts"thisgoesinmytestfile1:"$stdout=old_stdoutputs"thisshouldbebackontheconsole"这是输出。r
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
在许多ruby类之间共享记录器实例的最佳(正确)方法是什么?现在我只是将记录器创建为全局$logger=Logger.new变量,但我觉得有更好的方法可以在不使用全局变量的情况下执行此操作。如果我有以下内容:moduleFooclassAclassBclassC...classZend在所有类之间共享记录器实例的最佳方式是什么?我是以某种方式在Foo模块中声明/创建记录器还是只是使用全局$logger没问题? 最佳答案 在模块中添加常量:moduleFooLogger=Logger.newclassAclassBclassC..