어제의 솔루션을 사용 펄은 C++ 홍보되는 :. (비록 아마 오히려 서투른) 펄 스크립트 표준 입력에서 Valgrind의의 출력을 읽는 간단한 ogrammer 나는 C++로 그것을하기로되어있다. 나는 전에 std::regex
을 사용하지 않았으며 이것에 대해 조금 배우는 것이 필요하다. 이 std::regex
의 GCC의 현재 버전의 버그가 내가 부스트에서 구현을 사용하는 것 같다 때문에
#include "boost/regex.hpp"
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <stdexcept>
#include <string>
#include <vector>
namespace re = boost;
long to_long(std::string const& s)
{
return strtol(s.c_str(), 0, 10);
}
template <typename T>
static void insert(T& map, std::string const& address, std::string const& call, size_t size)
{
if (!map.insert(std::make_pair(address, std::make_pair(call, size))).second)
std::cout << "WARNING: duplicate address for " << call << ": " << address << "\n";
}
template <typename T>
static void erase(T& map, std::string const& address, std::string const& call)
{
auto it(map.find(address));
if (it == map.end() && address != "0x0")
std::cout << "WARNING: spurious address in " << call << "\n";
else
map.erase(it);
}
static void process(std::istream& in)
{
std::map<std::string, std::pair<std::string, size_t>> m;
std::vector<std::pair<re::regex, std::function<void(re::smatch&)>>> exps;
exps.emplace_back(re::regex(".*(malloc\\((.*)\\)) = (.*)"), [&](re::smatch& results){
::insert(m, results[3], results[1], ::to_long(results[2]));
});
exps.emplace_back(re::regex(".*(free\\((.*)\\))"), [&](re::smatch& results){
::erase(m, results[2], results[1]);
});
exps.emplace_back(re::regex(".*(calloc\\((.*),(.*)\\)) = (.*)"), [&](re::smatch& results){
::insert(m, results[4], results[1], ::to_long(results[2]) * ::to_long(results[3]));
});
exps.emplace_back(re::regex(".*(realloc\\((.*),(.*)\\)) = (.*)"), [&](re::smatch& results){
::erase(m, results[2], results[1]);
::insert(m, results[4], results[1], ::to_long(results[3]));
});
for (std::string line; std::getline(in, line);)
{
re::smatch results;
for (auto it(exps.begin()), end(exps.end()); it != end; ++it)
{
if (re::regex_match(line, results, it->first))
{
(it->second)(results);
break;
}
}
}
size_t total{0};
for (auto it(m.begin()), end(m.end()); it != end; ++it)
{
std::cout << "leaked memory at " << it->first << " " << "from " << it->second.first << "\n";
total += it->second.second;
}
std::cout << "total leak: " << total << "\n";
}
int main(int, char*[])
{
try
{
::process(std::cin);
}
catch (std::exception const &ex)
{
std::cerr << "ERROR: " << ex.what() << "\n";
}
}
: 그래서 여기에 C++ 솔루션입니다. 버전을 쉽게 전환 할 수 있습니다. re
을 boost
대신 std
의 별칭으로 정의하십시오.
예, 가능한 출력을 보여주는 예입니다. 스크립트를 시험해 봅시다 - 고마워요! 오, 패턴에 맞지 않는 모든 선을 무시하도록 만들 수 있습니까? –
아주 좋습니다. 하나의 질문 : 이것은 'realloc'의 다양한 가능성을 설명합니까? 똑바로 새로운'malloc '일 수도 있고, 기존 주소를 이동할 수도 있습니다. (또한'free (0)'은 허위가 아닙니다 :-). –
해충이 될 수있어서 유감입니다. 최종 유출 액을 더할 수 있습니까? Valgrind의 보고서와 비교하고 싶습니다. –