【问题标题】:Backtrace statistics for heap allocations - where is it called from and how many times?堆分配的回溯统计信息 - 它从哪里调用以及调用了多少次?
【发布时间】:2016-05-13 09:03:50
【问题描述】:

我需要知道我的程序中的哪些地方调用了malloc/new,并且对于每个这样不同的地方,多少次。关于内存分配的自上而下函数调用分析。

是否有任何工具可以收集此类统计信息? (malloc/new 主要通过std::vector 成员函数调用。)

【问题讨论】:

  • 如果你在 Linux 上,valgrind 会有所帮助。否则,也许在 malloc/free 的输出中使用像 gprof 和 grep 这样的分析器?
  • 我如何使用 Valgrind 或 gprof 来找出来自特定源代码位置的 malloc/new 调用的数量?或者,更好的是找出热点,即大部分内存分配发生的源代码位置?
  • 对于 valgrind,也许抑制可能有助于查明可疑的代码区域。但可能,探查器更好。
  • 哪个分析器?我已经尝试过 gprof 和 Intel VTune,但没有看到我正在寻找的统计数据。
  • 如果你使用 Visual Studio,试试vld

标签: c++ c statistics malloc new-operator


【解决方案1】:

大多数 C++ 运行时的调试版本都提供了一定程度的调试钩子来协助分配等。

更可定制的替代方法是编写自己的 operator newoperator delete 等来提供您想要的功能(例如,接受文件、行和函数名称作为参数,并在内部完成计数和日志记录)。将它们与预处理器 __FILE____LINE__ 等连接起来,为方便起见,使用宏来替换 newdelete(ATL/MFC 使用这种技术)。

如果重点是单个容器,最好的办法就是编写自己的分配器并用它创建vector

std::vector<int, MyAllocator> my_vector;
// or...
using MyVector = std::vector<int, MyAllocator>;
MyVector my_vector;

替换newdelete 的示例想法;

void* operator new(std::size_t count, int line, char const* file)
{
    auto p = ::malloc(count);
    std::printf("Allocate new @ %s:%d (%p)\n", file, line, p);
    return p;
}

void operator delete(void* pointer) noexcept
{
    std::printf("Deallocate pointer (%p)\n", pointer);
    ::free(pointer);
}

#define NEWIT new (__LINE__, __FILE__)
#define new NEWIT

int main()
{
    //auto p = new (__LINE__, __FILE__) int{};
    auto p = new int{};
    delete p;
}

【讨论】:

  • 我有许多不同的向量,因此自定义分配器需要大量代码更改。如何编写这样一个自定义的new 运算符?我需要在那里找出回溯并为每个不同的 bt 增加一些计数器。我想到了这个解决方案,但我想知道是否有用于此任务的工具。
  • @DanielLangr。我添加了代码(可能)看起来的示例。您需要扩展它并将其适当地放置在代码中(通常位于 cpp 文件的顶部),以通过代码库获得结果。您还可以将newdelete 也放入它们自己的cpp 文件中。
  • 考虑到您在“热点”问题上所做的 cmets,我也会查看您平台上的分析器。
  • 谢谢,但这无济于事。在我的代码和 new 之间通常有 5 到 10 个嵌套函数调用。例如,Libstdc++ 向量的实现由许多嵌套调用组成。 new 隐藏在内部深处的某个地方。我需要在我的代码中找到相应的行,而不是在 STL 实现中。
  • 哪个分析器?我试过 gprof 和 VTune,但没有找到对 newmalloc 的调用次数。它只是告诉我在其中花费了多少时间。
【解决方案2】:

我刚刚发现 Valgrind 完全符合我的需要。也就是说,使用 Callgrind 工具和 Kcachegrind 或 Qcachegrind 中的可视化,它向我显示了调用图以及每条边的调用次数。希望这对其他人也有帮助。

【讨论】:

    【解决方案3】:

    Open|SpeedShop 工具可以进行内存跟踪分析。它提供的数据在User Manual, page 96 中有描述。它似乎提供了调用路径和调用次数。
    请注意,Open|SpeedShop 可能很难构建。 Here's 构建指南,请注意您的操作系统的附加组件列表。您需要构建“CBTF”版本来启用内存跟踪分析。

    【讨论】:

    • 我刚刚发现 Valgrind 完全符合我的要求。即,使用 Callgrind 工具和 Kcachegrind 或 Qcachegrind 中的可视化,它向我显示了调用图以及每条边的调用次数。无论如何感谢您的帮助和建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2013-09-09
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 2017-05-22
    相关资源
    最近更新 更多