У меня нетрадиционный метод, помогающий найти предполагаемую утечку в коде, который я использовал бесчисленное количество раз, и он очень эффективен.Очевидно, что это не единственный или лучший способ найти утечки, но это уловка, которую вы должны иметь в своей сумке.
В зависимости от глубины вашего знания кода, вы можете иметь в виду пару подозрительных мест.Что я делал в прошлом, так это нацеливался на эти подозрительные места (усиливая утечку).Это можно сделать, просто поместив цикл вокруг подозрительного места, чтобы он вызывался не один, а много раз, обычно тысячи, но это зависит от размера основного распределения.Хитрость заключается в том, чтобы знать, где поставить петлю.Как правило, вы хотите переместить стек вызовов в место, где в цикле ожидается освобождение всей выделенной памяти.Во время выполнения используйте perfmon для просмотра приватных байтов и рабочего набора, когда он достигает пика, вы обнаружили утечку.С этого момента вы можете сузить область цикла до стека вызовов до нуля при утечке.
Рассмотрим следующий пример (может показаться хромым):
char* leak()
{
char* buf = new char[2];
buf[0] = 'a';
buf[1] = '\0';
}
char* furtherGetResults()
{
return leak();
}
std::string getResults(const std::string& request)
{
return furtherGetResults();
}
bool processRequest(SOCKET client, const std::string& request)
{
std::string results;
results = getResults(request);
return send(client, results.c_str(), results.length(), 0) == results.length();
}
Егоне всегда легко найти утечку, если код распределен между отдельными модулями или даже в отдельных библиотеках.Это также трудно найти, потому что утечки настолько малы, но со временем могут стать большими.
Для начала вы можете поставить цикл вокруг вызова getResults ():
bool processRequest(SOCKET client, const std::string& request)
{
std::string results;
for (size_t i = 0; i < 1000000; i++) {
results = getResults(request);
}
return send(client, results.c_str(), results.length(), 0) == results.length();
}
Еслискачки использования памяти увеличивают утечку, после чего вы перемещаетесь вниз по стеку вызовов к getResults (), затем к nextGetResults () и так далее, пока не прибьете его.Этот пример чрезмерно упрощает технику, но в рабочем коде, как правило, в каждой вызываемой функции намного больше кода, и его труднее сузить.
Эта опция может быть не всегда доступна, но когда она находитпроблема очень быстро.