c – 解释Valgrind的trace-malloc输出

前端之家收集整理的这篇文章主要介绍了c – 解释Valgrind的trace-malloc输出前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
Valgrind是一个优秀的内存调试器,它的选项是–trace-malloc = yes,它产生如下所示的内容
  1. --16301-- malloc(8) = 0x4EAD748
  2. --16301-- free(0x4EAD748)
  3. --16301-- free(0x4EAD498)
  4. --16301-- malloc(21) = 0x4EAD780
  5. --16301-- malloc(8) = 0x4EAD838
  6. --16301-- free(0x4EAD6F8)
  7. --16301-- calloc(1,88) = 0x4EAD870
  8. --16301-- realloc(0x0,160)malloc(160) = 0x4EB1CF8
  9. --16301-- realloc(0x4EB9F28,4) = 0x4EBA060

有没有一个工具来解析这个输出,并告诉我每个地址是否没有正确分配和释放匹配的一对?

GCC与mtrace()函数和mtrace命令行工具类似,但格式不同.

奖金问题:是否可以在“绝对丢失”语句旁边输出实际地址?

(我将这个“C”和“C”标记为最有可能与Valgrind一起使用的两种语言.)

解决方法

昨天的解决方案使用perl来分析输出.显然,作为C程序员,我应该在C中做.我以前没有使用std :: regex,需要先了解一下.所以这里是一个C解决方案:
  1. #include "boost/regex.hpp"
  2. #include <functional>
  3. #include <iostream>
  4. #include <iterator>
  5. #include <map>
  6. #include <stdexcept>
  7. #include <string>
  8. #include <vector>
  9.  
  10. namespace re = boost;
  11.  
  12. long to_long(std::string const& s)
  13. {
  14. return strtol(s.c_str(),10);
  15. }
  16.  
  17. template <typename T>
  18. static void insert(T& map,std::string const& address,std::string const& call,size_t size)
  19. {
  20. if (!map.insert(std::make_pair(address,std::make_pair(call,size))).second)
  21. std::cout << "WARNING: duplicate address for " << call << ": " << address << "\n";
  22. }
  23.  
  24. template <typename T>
  25. static void erase(T& map,std::string const& call)
  26. {
  27. auto it(map.find(address));
  28. if (it == map.end() && address != "0x0")
  29. std::cout << "WARNING: spurIoUs address in " << call << "\n";
  30. else
  31. map.erase(it);
  32. }
  33.  
  34. static void process(std::istream& in)
  35. {
  36. std::map<std::string,std::pair<std::string,size_t>> m;
  37.  
  38. std::vector<std::pair<re::regex,std::function<void(re::smatch&)>>> exps;
  39. exps.emplace_back(re::regex(".*(malloc\\((.*)\\)) = (.*)"),[&](re::smatch& results){
  40. ::insert(m,results[3],results[1],::to_long(results[2]));
  41. });
  42. exps.emplace_back(re::regex(".*(free\\((.*)\\))"),[&](re::smatch& results){
  43. ::erase(m,results[2],results[1]);
  44. });
  45. exps.emplace_back(re::regex(".*(calloc\\((.*),(.*)\\)) = (.*)"),results[4],::to_long(results[2]) * ::to_long(results[3]));
  46. });
  47. exps.emplace_back(re::regex(".*(realloc\\((.*),results[1]);
  48. ::insert(m,::to_long(results[3]));
  49. });
  50.  
  51. for (std::string line; std::getline(in,line); )
  52. {
  53. re::smatch results;
  54. for (auto it(exps.begin()),end(exps.end()); it != end; ++it)
  55. {
  56. if (re::regex_match(line,results,it->first))
  57. {
  58. (it->second)(results);
  59. break;
  60. }
  61. }
  62. }
  63.  
  64. size_t total{0};
  65. for (auto it(m.begin()),end(m.end()); it != end; ++it)
  66. {
  67. std::cout << "leaked memory at " << it->first << " " << "from " << it->second.first << "\n";
  68. total += it->second.second;
  69. }
  70. std::cout << "total leak: " << total << "\n";
  71. }
  72.  
  73. int main(int,char*[])
  74. {
  75. try
  76. {
  77. ::process(std::cin);
  78. }
  79. catch (std::exception const &ex)
  80. {
  81. std::cerr << "ERROR: " << ex.what() << "\n";
  82. }
  83. }

因为gcc的当前版本的std :: regex似乎是错误的,所以我使用了Boost的实现.应该很容易切换版本:只需将re定义为std的别名,而不是boost.

猜你在找的C&C++相关文章