计算对象实例的最简单方法
我想知道在某个执行点分配的某些对象的实例的确切数量。主要是为了寻找可能的内存泄漏(我主要使用 RAII,几乎没有新的,但在添加新元素或类似的东西之前我仍然可能会忘记向量上的 .clear() )。 Ofc 我可以有一个
atomic<int> cntMyObject;
- 在析构函数中,++ 在构造函数中增加,cpy 构造函数(我希望我涵盖了所有内容:))。 但这是对每个类的硬编码。在“释放”模式下禁用它并不简单。 那么有没有一种简单优雅的方法可以轻松禁用对对象实例的计数呢?
I would like to know the exact number of instances of certain objects allocated at certain point of execution. Mostly for hunting possible memory leaks(I mostly use RAII, almost no new, but still I could forget .clear() on vector before adding new elements or something similar). Ofc I could have an
atomic<int> cntMyObject;
that I -- in destructor, ++ increase in constructor, cpy constructor(I hope I covered everything :)).
But that is hardcoding for every class. And it is not simple do disable it in "Release" mode.
So is there any simple elegant way that can be easily disabled to count object instances?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
有一个“计数对象”类,在其构造函数和析构函数中执行正确的引用计数,然后派生您要从中跟踪的对象。然后,您可以使用奇怪的重复模板模式来获取您想要跟踪的任何对象类型的不同计数。
Have a "counted object" class that does the proper reference counting in its constructor(s) and destructor, then derive your objects that you want to track from it. You can then use the curiously recurring template pattern to get distinct counts for any object types you wish to track.
您可以在
DEBUG
模式下应用此方法,调用
ObjectCount::showCount()
方法将返回创建的对象的计数。you can apply this approach
at
DEBUG
mode, invoking ofObjectCount::showCount()
method will return count of object(s) created.最好使用内存分析和内存分析。泄漏检测工具,例如 Valgrind 或 Rational Purify。
如果您不能并且想要实现自己的机制,那么
您应该为您的类重载
new
和delete
运算符,然后在其中实现内存诊断。查看此 C++ 常见问题解答,了解如何操作以及您应该采取哪些预防措施。
Better off to use memory profiling & leak detection tools like Valgrind or Rational Purify.
If you can't and want to implement your own mechanism then,
You should overload the
new
anddelete
operators for your class and then implement the memory diagnostic in them.Have a look at this C++ FAQ answer to know how to do that and what precautions you should take.
这是类似的工作示例: http://www.almostinfinite.com/memtrack.html< /a> (只需复制页面末尾的代码并将其放入 Memtrack.h 中,然后运行 TrackListMemoryUsage() 或其他函数之一来查看诊断信息)
它会覆盖 new 运算符并执行一些神秘的宏使它用信息“标记”每个分配,使其能够计算对象的实例数量以及它们正在使用的内存量。但它并不完美,他们使用的宏在某些条件下会崩溃。如果您决定尝试此操作,请确保将其包含在任何标准标头之后。
This is a sort of working example of something similar: http://www.almostinfinite.com/memtrack.html (just copy the code at the end of the page and put it in Memtrack.h, and then run TrackListMemoryUsage() or one of the other functions to see diagnostics)
It overrides operator new and does some arcane macro stuff to make it 'stamp' each allocation with information that allow it to count how many instances of an object and how much memory they're usingusing. It's not perfect though, the macros they use break down under certain conditions. If you decide to try this out make sure to include it after any standard headers.
在不了解您的代码和要求的情况下,我看到了 2 个合理的选择:
a) 使用
boost::shared_ptr
。它具有您建议内置的原子引用计数,并负责内存管理(这样您就不会真正关心查看计数)。它的引用计数可通过use_count()
成员获得。b) 如果 a) 的含义(例如处理指针和到处都有
shared_ptrs
或可能的性能开销)对您来说不可接受,我建议您简单地使用可用的工具进行内存泄漏检测(例如Valgrind,见上文),它将在程序退出时报告您的松散对象。并且无需使用侵入性帮助程序类(无论如何仅调试)跟踪对象计数,这只会弄乱您的代码,恕我直言。Without knowing your code and your requirements, I see 2 reasonable options:
a) Use
boost::shared_ptr
. It has the atomic reference counts you suggested built in and takes care of your memory management (so that you'd never actually care to look at the count). Its reference count is available through theuse_count()
member.b) If the implications of a), like dealing with pointers and having
shared_ptrs
everywhere, or possible performance overhead, are not acceptable for you, I'd suggest to simply use available tools for memory leak detection (e.g. Valgrind, see above) that'll report your loose objects at program exit. And there's no need to use intrusive helper classes for (anyway debug-only) tracking object counts, that just mess up your code, IMHO.我们曾经有一个带有内部计数器的基类并从中派生的解决方案,但我们将其全部更改为 boost::shared_ptr,它保留了引用计数器并为您清理了内存。 boost智能指针系列非常有用:
Boost 智能指针
We used to have the solution of a base class with internal counter and derive from it, but we changed it all into boost::shared_ptr, it keeps a reference counter and it cleans up memory for you. The boost smart pointer family is quite useful:
boost smart pointers
我的方法,将泄漏计数输出到调试输出(通过我们的代码库中实现的 DebugPrint 函数,用您自己的调用替换该调用...)
示例用法:
My approach, which outputs leakage count to Debug Output (via the DebugPrint function implemented in our code base, replace that call with your own...)
Example usage:
一些答案中讨论了向各个类添加计数器。然而,它需要选择要计数的类并以一种或另一种方式修改它们。下面的假设是,您添加此类计数器是为了查找错误,其中某些类的对象数量比预期的要多。
简要回顾一下已经提到的一些事情:对于真正的内存泄漏,当然有 valgrind:memcheck 和泄漏清理程序。然而,对于没有真正泄漏的其他场景,它们没有帮助(未清除的向量、具有从未访问过的键的映射条目、shared_ptrs 的循环,...)。
但是,由于没有提到这一点:在 valgrind 工具套件中还有 Massif,它可以为您提供有关所有已分配内存块及其分配位置的信息。但是,我们假设 valgrind:massif 也不适合您,并且您确实需要实例计数。
为了偶尔寻找错误 - 如果您愿意接受一些黑客解决方案并且上述选项不起作用 - 您可能会考虑以下内容: 如今,堆上的许多对象实际上由智能指针保存。这可能是标准库中的智能指针类,也可能是您使用的相应帮助程序库的智能指针类。技巧如下(以shared_ptr为例):通过修补shared_ptr实现,即通过将实例计数添加到shared_ptr类,您可以一次获取许多类的实例计数器。然后,对于某些类Foo,属于shared_ptr的计数器将为您指示 Foo 类的实例数量。
当然,它不如直接将计数器添加到相应的类那么准确(不计算仅由原始指针引用的实例),但对于您的情况来说,它可能足够准确。当然,这并不是要永久更改智能指针类 - 仅在错误搜寻期间更改。至少,智能指针的实现并不太复杂,因此修补它们很简单。
Adding counters to individual classes was discussed in some of the answers. However, it requires to pick the classes to have counted and modify them in one way or the other. The assumption in the following is, you are adding such counters to find bugs where more objects of certain classes are kept alive than expected.
To shortly recap some things mentioned already: For real memory leaks, certainly there is valgrind:memcheck and the leak sanitizers. However, for other scenarios without real leaks they do not help (uncleared vectors, map entries with keys never accessed, cycles of shared_ptrs, ...).
But, since this was not mentioned: In the valgrind tool suite there is also massif, which can provide you with the information about all pieces of allocated memory and where they were allocated. However, let's assume that valgrind:massif is also not an option for you, and you truly want instance counts.
For the purpose of occasional bug hunting - if you are open for some hackish solution and if the above options don't work - you might consider the following: Nowadays, many objects on the heap are effectively held by smart pointers. This could be the smart pointer classes from the standard library, or the smart pointer classes of the respective helper libraries you use. The trick is then the following (picking the shared_ptr as an example): You can get instance counters for many classes at once by patching the shared_ptr implementation, namely by adding instance counts to the shared_ptr class. Then, for some class Foo, the counter belonging to shared_ptr<Foo> will give you an indication of the number of instances of class Foo.
Certainly, it is not quite as accurate as adding the counters to the respective classes directly (instances referenced only by raw pointers are not counted), but possibly it is accurate enough for your case. And, certainly, this is not about changing the smart pointer classes permanently - only during the bug hunting. At least, the smart pointer implementations are not too complex, so patching them is simple.
这种方法比此处的其他解决方案简单得多。
为计数创建一个变量并将其设为静态。在构造函数中将该变量增加 +1,在析构函数中将该变量减少 -1。
确保初始化变量(它不能在标头内初始化,因为它是静态的)。
.h
.cpp
对于您创建的每个新实例,都会调用构造函数,totalObjects 会自动增加 1。
This approach is much simpler than the rest of the solutions here.
Make a variable for the count and make it static. Increase that variable by +1 inside the constructor and decrease it by -1 inside the destructor.
Make sure you initialize the variable (it cannot be initialized inside the header because its static).
.h
.cpp
For every new instance you make, the constructor is called and totalObjects automatically grows by 1.