Найти утечки памяти, вызванные умными указателями - PullRequest
17 голосов
/ 16 сентября 2008

Кто-нибудь знает «технику» для обнаружения утечек памяти, вызванных умными указателями? В настоящее время я работаю над большим проектом, написанным на C ++ , в котором интенсивно используются умные указатели со счетчиком ссылок. Очевидно, у нас есть некоторые утечки памяти, вызванные умными указателями, на которые все еще ссылаются где-то в коде, так что их память не освобождается. Очень трудно найти строку кода с «ненужной» ссылкой, которая приводит к тому, что соответствующий объект не будет свободным (хотя он больше не используется).

В сети я нашел несколько советов, которые предлагали собирать стеки вызовов операций увеличения / уменьшения счетчика ссылок. Это дает мне хороший совет, какой фрагмент кода вызвал увеличение или уменьшение счетчика ссылок.

Но мне нужен какой-то алгоритм, который группирует соответствующие «стеки вызовов увеличения / уменьшения» вместе. После удаления этих пар стеков вызовов, я надеюсь, у меня остался (по крайней мере) один «увеличенный стек вызовов», который показывает мне фрагмент кода с «ненужной» ссылкой, который вызвал освобождение соответствующего объекта. Теперь будет несложно исправить утечку!

Но есть ли у кого-нибудь идея для "алгоритма", который делает группировку?

Разработка происходит под Windows XP .

(надеюсь, кто-то понял, что я пытался объяснить ...)

EDIt: я говорю о утечках, вызванных циклическими ссылками.

Ответы [ 12 ]

1 голос
/ 16 сентября 2008

На вашем месте я бы взял журнал и написал бы быстрый скрипт, чтобы сделать что-то вроде следующего (у меня в Ruby):

def allocation?(line)
  # determine if this line is a log line indicating allocation/deallocation
end

def unique_stack(line)
  # return a string that is equal for pairs of allocation/deallocation
end

allocations = []
file = File.new "the-log.log"
file.each_line { |line|
  # custom function to determine if line is an alloc/dealloc
  if allocation? line
    # custom function to get unique stack trace where the return value
    # is the same for a alloc and dealloc
    allocations[allocations.length] = unique_stack line
  end
}

allocations.sort!

# go through and remove pairs of allocations that equal,
# ideally 1 will be remaining....
index = 0

while index < allocations.size - 1
  if allocations[index] == allocations[index + 1]
    allocations.delete_at index
  else
    index = index + 1
  end
end

allocations.each { |line|
  puts line
}

Это в основном проходит через журнал и фиксирует каждое распределение / освобождение и сохраняет уникальное значение для каждой пары, затем сортирует его и удаляет совпадающие пары, смотрите, что осталось.

Обновление: извините за все промежуточные правки (я случайно написал до того, как закончил)

0 голосов
/ 21 марта 2013

Первым шагом может быть узнать, какой класс протекает. Как только вы это знаете, вы можете найти, кто увеличивает ссылку: 1. поставить точку останова на конструктор класса, который обернут в shared_ptr. 2. вступите с отладчиком в shared_ptr при увеличении счетчика ссылок: посмотрите на переменную pn-> pi _-> use_count_ Возьмите адрес этой переменной путем вычисления выражения (что-то вроде этого: & this-> pn-> pi_.use_count_), вы получите адрес 3. В отладчике Visual Studio выберите «Отладка» -> «Новая точка останова» -> «Новая точка останова данных» ... Введите адрес переменной 4. Запустите программу. Ваша программа будет останавливаться каждый раз, когда некоторая точка в коде увеличивается и уменьшается счетчик ссылок. Затем вам нужно проверить, совпадают ли они.

...