Страницы

Поиск по вопросам

Показаны сообщения с ярлыком memory-leaks. Показать все сообщения
Показаны сообщения с ярлыком memory-leaks. Показать все сообщения

вторник, 18 февраля 2020 г.

Выделение памяти в С++ и аварийное завершение программы

#cpp #memory_leaks #memory_management


Допустим, у меня есть класс, который я создаю в самом начале программы, в его конструкторе
я выделяю память под какие-то другие объекты с помощью операторов new, а в его деструкторе
вызываю delete. Насколько такая практика приемлема и что произойдёт, если во время
работы программы её аварийно завершить (скажем, прихлопнуть через диспетчер задач).
Спасибо.
    


Ответы

Ответ 1



Если Ваше приложение будет "прихлопнуто" или аварийно завершено, то обычная выделенная память будет подчищена. Да, деструктор не будет вызван, но какое это имеет значение, если приложение уже упало. Поэтому, если просто выделили память себе под массив, а потом подчистили - все ок. Но в современном с++ явный вызов new/delete считается моветоном. Обычные unique_ptr/shared_ptr решают 90% подобных проблем и нивелируют необходимость в теле деструктора. Другое дело, если приложение выделят какие-то общие ресурсы - shared memory или междупроцессорные мютексы/семафоры. Тут могут быть проблемы.

воскресенье, 16 февраля 2020 г.

Выделение памяти в С++ и аварийное завершение программы

#cpp #memory_leaks #memory_management


Допустим, у меня есть класс, который я создаю в самом начале программы, в его конструкторе
я выделяю память под какие-то другие объекты с помощью операторов new, а в его деструкторе
вызываю delete. Насколько такая практика приемлема и что произойдёт, если во время
работы программы её аварийно завершить (скажем, прихлопнуть через диспетчер задач).
Спасибо.
    


Ответы

Ответ 1



Если Ваше приложение будет "прихлопнуто" или аварийно завершено, то обычная выделенная память будет подчищена. Да, деструктор не будет вызван, но какое это имеет значение, если приложение уже упало. Поэтому, если просто выделили память себе под массив, а потом подчистили - все ок. Но в современном с++ явный вызов new/delete считается моветоном. Обычные unique_ptr/shared_ptr решают 90% подобных проблем и нивелируют необходимость в теле деструктора. Другое дело, если приложение выделят какие-то общие ресурсы - shared memory или междупроцессорные мютексы/семафоры. Тут могут быть проблемы.

воскресенье, 9 февраля 2020 г.

Утечка памяти при многократном запуске потока

#java #многопоточность #memory_leaks


Доброго (CurrentTime) ,Столкнулся со странностью при многократном создании потока
и по завершению исполнения озу не освобождается, можете рассказать что тут происходит,
прошу извинений за вопрос тк новичок? 

public class MainClass {

public static void main(String[] args) throws InterruptedException {

    int i = 0;
    while (i < 100000) {
      TestThread test = new TestThread();
      test.start();
      i++;
    }

    System.gc();
    Thread.sleep(8000);

  }

}


Класс TestThread

public class TestThread extends Thread {

   public void run() {

    // Пустой

  }

}

    


Ответы

Ответ 1



Несколько возможных причин для такого поведения: Потоки не завершились на момент вызова System.gc. Потоки, хоть они ничего и не делают, требуют выделения ресурсов для запуска. Вы запускаете один за другим 100000 потоков, а затем вызываете сразу gc не дожидаясь их завершения. Часть потоков может быть не завершена на этот момент. Дождаться завершения работы потока можно с помощью Thread.join. Вызов System.gc не обязательно запускает сборщик мусора. Из документации к System.gc: Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. ... Вызов метода предлагает виртуальной машине Java приложить усилия для обработки неиспользуемых объектов, чтобы сделать память, которую они занимают, доступной для быстрого повторного использования. .... В общем, это рекомендация, которая не гарантирует сборку мусора. Сборка мусора произойдет когда виртуальная машина посчитает нужным. Можете еще почитать ответ на вопрос: «Как часто надо вызывать сборщик мусора?» Сборка мусора не обязательно освобождает память для ОС. Даже если сборка мусора запустится, нет никакой гарантии, что освобожденная память будет возвращена ОС для использования в других процессах. Освобождение памяти и выделение ее заново — ресурсоемкие задачи, которые могут оказать влияние на производительность клиентского (Вашего) кода. Поэтому разработчики JVM предусматривают сложные алгоритмы сборки мусора с минимальным влиянием на исполнение. В зависимости от настроек памяти JVM и используемого сборщика мусора память может быть сохранена для повторного использования Java (на очистку вообще не тратятся ресурсы) либо возвращена частично до определенного процентного порога (перераспределение памяти происходит в ограниченных масштабах). Подробнее о разных сборщиках мусора смотрите в документации к используемой Вами версии JVM. Можете также ознакомиться с обзорными статьями по теме: Статьи на сайте Oracle: Java HotSpot Garbage Collection; Теория и практика Java: Сборка мусора в HotSpot JVM; серия статей «Дюк, вынеси мусор!» на Хабре.

суббота, 8 февраля 2020 г.

Способы определить утечку памяти

#c #unix #memory_leaks #linux


Суть вопроса проста. Какие способы/инструменты есть для определения что память у
нас утекла?
ANSI C.
Для Unix-подобных ОС
x64-86
Нагуглил Hans Boehm garbage collector, но он то ли не работает с Linux x64, то ли
я совсем его криво использую - всё время выдаёт 65536 на GC_get__heap_size().

crtdbg не подходит из-за привязки к MSVS.
Изначально это была задача определить правильно ли я удаляю дерево, но переросло
в этот вопрос.    


Ответы

Ответ 1



Попробуйте Valgrind. Одна из программ Valgrinda, Memcheck, насколько я понимаю, соответствует вашим требованиям.

пятница, 10 января 2020 г.

Как использовать MAT с Android Studio?

#android #android_studio #android_sdk #memory_leaks


Я установил MAT,выгрузил HEAP из Android Device Monitor и теперь у меня есть .hprof
файл, как его проанализировать в MAT?
    


Ответы

Ответ 1



Что бы конвертировать .hprof выгруженный из Android Studio в MAТобразный .hprof необходимо проделать следующие действия. Открываем командную строку и идем в папку Android\sdk\platform-tool Затем вводим команду hprof-conv "путь к конвертируемому файлу" "путь к итоговому файлу" у меня это выглядело так: C:\Users\sh_am\AppData\Local\Android\sdk\platform-tools> hprof-conv "C:\Users\sh_am\Desktop\rambotv30.hprof" "C:\Users\sh_am\Desktop\4mat.hprof" Это создаст файл стандартный .hprof файл с именем которое вы указали у меня это 4mat.hprof Открывал файл в MAT все работает отлично

пятница, 20 декабря 2019 г.

Вызовет ли realloc утечку памяти?

#c #memory_leaks #realloc


Доброго времени суток! Есть код:

// mry_char*  - это wchar_t*
// mry_charsz - это sizeof(wchar_t)

void mry_strcat(mry_char* _dest, const mry_char const* _src) {
    const u32 dl = mry_strlen(_dest);
    const u32 sl = mry_strlen(_src);

    _dest = realloc(_dest, (dl + sl + 1) * mry_charsz);
    memmove(_dest + dl, _src, sl * mry_charsz);
    _dest[dl + sl] = '\0';
}


Cppcheck пишет:

Id: memleak
Кратко: Memory leak: _dest
Сообщение: Memory leak: _dest

First included by: mary.c

Строка 69: _dest[dl + sl] = '\0';


Я так понимаю, что утечка будет, если realloc переместит блок при возрастании размера,
так ли это?

UPD

Исправил выход за границы массива.
    


Ответы

Ответ 1



В своем коде вы должны рассчитывать на то, что realloc будет всегда перемещать блок, независимо от того, увеличивается ли его размер, уменьшается ли или вообще не меняется. Эти решения принимаются на основе неподконтрольных вам обстоятельств. То, что он может иногда и не переместиться - не более чем редкая и непредсказуемая удача. Утечка у вас образуется из-за того, что новое значение указателя _dest в наружный код никак не возвращается. Память, выделенная вашим realloc в общем случае становится утечкой всегда. Либо возвращайте новый _dest из функции через возвращаемое значение, либо работайте с ним "по ссылке", т.е. делайте его mry_char** параметром. (Да, если в результате работы realloc значение указателя _dest не изменилось, то формально возвращать его "не нужно", но ожидать этого в реальном коде - это полная белиберда. В общем случае значение указателя будет меняться.) Дополнительно, в связи именно c realloc утечка также может возникнуть, если realloc не сможет выделить память вообще. Тогда он вернет null-указатель, но старую память не освободит, т.е. внутри функции доступ к памяти, изначально указываемой _dest, вы потеряете. (Будет ли это полноценной утечкой зависит от того, сохранили ли вы еще какой-то путь доступа к этой памяти. Из вашего кода этого не видно.) Также, почему памяти выделяется только под dl + sl элементов, если потом делается _dest[dl + sl] = '\0'? Явный вылет за пределы выделенной памяти.

Ответ 2



Утечки как таковой из-за realloc не появляется - если вы не забудете потом удалить выделенную память. Другое дело, что вы 1. не проверяете результат realloc (и не сохраняете его) 2. выделяете недостаточно памяти (есть выход за границу) 3. Насколько я помню, для wchar_t надо записывать не '\0', а L'\0'

среда, 18 декабря 2019 г.

Утечки памяти в OpenCV

#cpp #память #opencv #memory_leaks


У меня в проекте есть такие строчки кода(с++):

Mat src = imread(fn);
cvtColor(src, src, CV_BGR2RGB); 


Всё это находится в вызываемой изредка функции.
Происходит, как я могу предположить следующее: 


по указателю src находится оригинальное изображение из файла.
cvtColor это изображение преобразовывает и кладёт под тем-же именем, но уже в другое
место в памяти, тем самым оставляя оригинальные данные без каких-либо имён.


Вопрос: будет ли в этом месте утечка памяти, т.е. освободится ли место, где были
оригинальные данные, на которые сейчас ничего не ссылается, после выхода из подпрограммы?
    


Ответы

Ответ 1



Согласен с @Costantino Rupert - утечки быть не должно, я сам такое использую постоянно и работает бывает недели без перезагрузки, поэтому точно знаю что утечек нет. Я чуть менее чем уверен, что это нюансы конкретной реализации диспетчера памяти - попробуйте скомпилировать другим компилятором, или даже на другой платформе, скорее всего проблема отпадёт. Еще попробуйте другим компилятором пересобрать OpenCV

воскресенье, 8 декабря 2019 г.

Освобождение динамической памяти перед завершением

#cpp #c #memory_leaks


Почему необходимо избегать утечек памяти в процессе работы программы понятно.
Но зачем нужно освобождать память динамически объявленных переменных перед завершением
работы программы?

Единственный ответ, до которого мы с коллегами пришли: чтобы "зомби" (в Linux), если
он появится после завершения программы, занимал минимальное место.

В остальных случаях ОС сама подотрет все, что было занято, разве нет? 

Какие еще негативные последствия могут возникнуть?
    


Ответы

Ответ 1



Зомби (в *nix) места в памяти не занимает (в том смысле, который вы в это вкладываете). Он занимает одну запись в стуктуре планировщика в ядре. А так, да, нормальная современная ОС (в которых почти все пишут) "все подотрет" за процессом. Почти все. С сегментами shared memory проблемы будут, но это в лоб не автоматизируется, поскольку удалять или оставлять -- зависит от сути прикладной задачи. Если же вдруг будете писать программы под что-то другое (какой-нибудь самодельный монитор для real-time embedded), то может и придется убирать память самому.

Ответ 2



Смотрите. Никаких причин освобождения памяти перед завершением программы, кроме чисто эстетических, нет. Память всё равно вернётся системе после смерти процесса. Однако, довольно часто объекты в своём деструкторе совершают дополнительные действия. Закрывают транзакцию в базе данных, корректно закрывают онлайн-сессию, сбрасывают изменённые данные на диск и т. п. Таким образом, если такой объект «утечёт», то программа после завершения оставит что-то в некорректном состоянии. Если ваша программа маленькая, вы можете её полностью обозреть, и вы уверены, что кроме утечек памяти ничего плохого от пропущенных деструкторов не случится — можете смело оставлять в конце память. Но если ваш проект большой, то скорее всего у вас не будет полного обзора того, что какой модуль делает. В такой ситуации лучше придерживаться дисциплинированного подхода и чистить за собой.

Ответ 3



Перед завершением работы программы нужно убедиться, что разделяемые ресурсы освобождены, например, соединения с базой данных и веб-серверами закрыты. Серверы какое-то время могут считать ваш клиент всё ещё подключенным, что нежелательно. Следует сбросить данные на диск в файлах, если вам есть дело до их содержимого. Если вам всё равно, то можно не закрывать — система справится сама. Освобождать память обычно ненужно, хоть это и является правилом хорошего тона. Более того, если ваша программа выделила очень много сложных объектов в памяти, и память частично свалилась в своп, то может быть выгодно не освобождать память, чтобы не заставлять систему вытаскивать информацию с диска только для того, чтобы её выбросить. Если вы хотите быстро завершить процесс, то можете аккуратно разрушить объекты, которые хранят ссылки на разделяемые ресурсы, а потом просто убить процесс. Более того, в идеале программа должна корректно обрабатывать случай убийства процесса в любой момент. Данные при этом не должны быть повреждены. Отработка случая жёсткого убийства процесса без аккуратного освобождения памяти и ресурсов — это важный момент при разработке программ. Из-за этого ваша программа не должна перестать быть работоспособной (например, из-за повреждения конфигурационных файлов).

Ответ 4



Код на C работает в таких местах где никакой ОС может вообще не существовать и в помине. Компьютерная память является общим ресурсом, крайне сложным и дорогим в производстве. Не стоит думать что она принадлежит лично Вам. Например в данный момент на хосте откуда я пишу вам это сообщение запущено 106 процессов, написанных другими людьми(физически они все используют DDR за которую заплатил лично я). Представьте что было бы с ними если бы автор каждого из них думал только о себе и не занимался высвобождением памяти, а наоборот пытался схватить её как можно больше будучи одержимым идеей об уникальноси и сверхполезности своей поделки. Момент прекращения использования того или иного ресурса в программе(в частности памяти) может не совпадать с её завершением. Но если вы пишите какую-то мелкую прикладную программу для популярной ОС в которой при этом еле еле аллокируется 100кБ, то можно конечно понадеется и на ОС и на язык с автоматической сборкой мусора. В принципе ничем страшным это не грозит, если конечно программа внезапно не разрастется до больших размеров и толпы пользователей в придачу. Тогда однозначно стоит начинать более серьезно задумываться о распределении общих ресурсов, в частности и памяти.

Ответ 5



В C++ операторы delete и delete[], которыми Вы освобождаете память, вызывают деструкторы объектов. Если в деструкторе есть какая-то логика (например, сериализация), она не сработает, и какие-то данные могут быть потеряны. Замечу так же, что функция free деструктор не вызывает, ее задача - освободить память. Обычно освобождение памяти считается хорошим тоном. Даже если у Вас нет в деструкторах логики сейчас, это не значит, что ее не появится там в будущем (и тогда придется перелопатить весь проект). Если Ваша программа завершается в этом месте сейчас, то это не значит, что в будущем она не будет завершаться гораздо позже (и Вы получите уже значимую утечку памяти). То есть, выполняя очистку памяти, Вы получаете меньше проблем в будущем. Программа становится более расширяемой и поддерживаемой. Однако, бывает, что память не освобождается специально. Например, в C++ имеется проблема с порядком инициализации/деинициализации статических переменных, которая при выявлении часто решается при помощи синглтона. Такой синглтон должен существовать и после завершения функции main, так как после как раз и происходит деинициализация статических переменных. Поэтому он создается при помощи new и никогда не освобождается.

суббота, 30 ноября 2019 г.

Может ли Activity, обращающаяся к статическим полям быть причиной утечек памяти?

#android #memory_leaks


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

Стал вопрос оптимизации, ищу причины. Первая идея и мысль связана с логикой загрузки
приложения. Сначала я показываю активити-заглушку (пока загружаются все необходимые
данные), эти данные пишутся в статические поля некоторых классов для последующих операций,
то есть идет обращение к статическим ссылкам, которые не умирают. 

После вызывается finish, и я показываю активити, в которой идет все взаимодействие
юзера с приложением. Может обращение к статическим ссылкам быть одной из причин того,
что, например, активити не убивается при вызове finish и образуется утечка памяти?
    


Ответы

Ответ 1



Вообще, нет особой разницы в этом плане Java это чистая, или Android приложение. Хотя, я особо никогда не вникал в разницу между Dalvik и Hotspot jvm, но предполагаю, что GC работает примерно одинаково. Memory leak у вас может быть в случае, если static переменная в себе содержит линк на другой объект. Если вам уже не нужен этот объект, то, если вы забудете обнулить ссылку, он всё равно будет в памяти. Хотя, это сложно назвать именно утечкой, если брать в расчёт, что ссылка будет жить на протяжении жизни приложения. Формально, это будет перманентный синглтон. Может обращение к статическим ссылкам быть одной из причин того, что, например, активити не убивается при вызове finish и образуется утечка памяти? Вот это довольно интересный вопрос в контексте Android, так как в этой ОС жизненный цикл приложений весьма, хм, специфичный. Тут всё зависит, само собой, от того, что за переменные у вас статические. Так как в вопросе нету специфики, будет рассматривать абстрактные ситуации. Часто утечки бывают из-за context'а. Скажем, есть у вас: public class SomeClass extends SurfaceView { private static Context myContext; public MyInnerClass(Context context){ myContext = context; // здесь начинается печалька } } Даже если не останется ссылок на объекты SomeClass (вспомним, что если нет ссылок, то GC должен быть очистить память), скажем, когда Activity, которая показывала эту SurfaceView закрылась, статичная ссылка на Context (и любые другие статические переменные / константы в SomeClass останутся). Вы можете считать, что все они станут причиной утечкой памяти, так как нет возможности GC утилизировать Context. В контексте Android'а, могу сказать, что причиной утечек часто бывают как раз-такие ссылки на Activity, Context, View, Drawable, да и вообще любые объекты, которые содержат в себе ссылки на контейнер Activity или Context. Так же причиной могут быть нестатические внутренние классы (типо Runnable, которые могут содержать ссылки на Activity). Если же развить тему и уточнить вопрос: а вы уверены, что причина именно в static переменных? Handler с postDelay точно так же может стать причиной утечек. Можно почитать про возможные причины в блоге badoo. Или же в Android developers blog посмотреть пример утечек с Drawable. По сему, я бы сначала с помощью соответствующих утилит выявил, где конкретно утечки происходят, а уже от этого и отталкивался бы потом.

Ответ 2



Насколько я понимаю работу системы Android, то при вызове finish() активити вовсе принудительно не уничтожается (не удаляется из памяти), она только помечается "не активной" - происходит вызов методов завершения (onPause(), onStop(), onDestroy()) и манипуляции со списком переходов. На передний план отображается активити с вершины стека. Сама же "финишированная" активити существует в памяти до того момента, пока GC не решит провести очистку по каким то своим соображениям. Соответственно, если активити имеет статические ссылки (которые существуют до окончания работы приложения), то уничтожена сборщиком мусора она не будет, даже не смотря на то, что и помечена "не активной", так как есть жесткая ссылка - на лицо явная утечка памяти. Вообще, Android Studio в последней версии (1.5 на сегодняшний день) включает Memory Monitor для поиска утечек (инструменты HPROF Viewer и Allocation Tracker). Разумно будет воспользоваться ими и посмотреть, что же происходит. Здесь вы можете принудительно вызвать GC (очистку памяти) и проследить за судьбой своей активити и что ее держит в этом бренном мире. Очень часто там ждут неожиданные сюрпризы. Смотрите так же статью по утечкам памяти на офф.сайте

Ответ 3



Не нужно хранить глобальные переменные в активити. Если Вам нужно сохранить переменные на весь жизненный цикл приложения, то есть 2 варианта, которые позволяют это сделать: Первый - это создать свой класс наследник Application, где определить эти глобальные переменные и написать гетеры и сеттеры для них. public class MyApplication extends Application { private MyCustomObject myGlobalField; @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); } @Override public void onCreate() { super.onCreate(); } @Override public void onLowMemory() { super.onLowMemory(); } @Override public void onTerminate() { super.onTerminate(); } public MyCustomObject getMyGlobalField() { return this.myGlobalField; } public void setMyGlobalField(MyCustomObject myGlobalField) this.myGlobalField = myGlobalField; } } Не забудьте указать Ваш класс приложения в манифесте: Затем, в Ваших активити вы получаете доступ к этим полям: MyApplication myApplication = (MyApplication)getApplicationContext(); MyCustomObject myGlobalField = myApplication.getMyGlobalField(); Второй вариант - это хранить все глобальные данные в SharedPreferences. Но, это вариант не подходит, если вы хотите сохранить свои custom Object, а не обычные примитивы.

Ответ 4



Хотя статические переменные и нарушают принцип взаимодействия между Activity (правильно передавать данные через Intent, но придется научить все свои объекты сериализоваться), но утечек памяти это вызывать не должно. Надо искать в других местах. Например, стандартная утилита из Android SDK 'android-sdk\tools\monitor.bat' имеет минимальный функционал для отслеживания выделения памяти.

вторник, 25 июня 2019 г.

При старте приложения используется 86% оперативной памяти(HeapSize)

Я разрабатываю приложение для Андроида(платформа Xamarin). На текущий момент это приложение является прототипом(внутри нет ничего тяжелого). Было добавленна библиотека app7compat support,так же был заимплементен тулбар с DrawerLayout. Провожу тесты на устройстве Samsung Galaxy S4 Active и если корректно понимаю,то это скорее всего баг\глюк, т.к. при запуске приложения Android Device Monitor показывает следующее :
Как такое вообще возможно? Моя активити содержит:
Тулбар(с Drawer layout) Пару контролов,таких как Imageview/ImageButtons
Как я говорил раньше,это происходит сразу после запуска. Чем же может быть занята память на 86%, если даже нету никаких цпу\гпу вычислений? Почему это происходит?


Ответ

Это нормально. Приложение занимает 86% от выделенной в данный момент для него памяти.
Много конечно, но не смертельно.
Гляньте лучше сколько памяти всего может быть выделено. В случае андроид это делается так:
Runtime rt = Runtime.getRuntime(); long maxMemory = rt.maxMemory(); Log.v("onCreate", "maxMemory:" + Long.toString(maxMemory));
или так:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); int memoryClass = am.getMemoryClass(); Log.v("onCreate", "memoryClass:" + Integer.toString(memoryClass));
Если не ошибаюсь для S4 это 192 Mb (201326592 b)

четверг, 18 апреля 2019 г.

Утечка памяти при многократном запуске потока

Доброго (CurrentTime) ,Столкнулся со странностью при многократном создании потока и по завершению исполнения озу не освобождается, можете рассказать что тут происходит, прошу извинений за вопрос тк новичок?
public class MainClass {
public static void main(String[] args) throws InterruptedException {
int i = 0; while (i < 100000) { TestThread test = new TestThread(); test.start(); i++; }
System.gc(); Thread.sleep(8000);
}
}
Класс TestThread
public class TestThread extends Thread {
public void run() {
// Пустой
}
}


Ответ

Несколько возможных причин для такого поведения:
Потоки не завершились на момент вызова System.gc
Потоки, хоть они ничего и не делают, требуют выделения ресурсов для запуска. Вы запускаете один за другим 100000 потоков, а затем вызываете сразу gc не дожидаясь их завершения. Часть потоков может быть не завершена на этот момент. Дождаться завершения работы потока можно с помощью Thread.join
Вызов System.gc не обязательно запускает сборщик мусора.
Из документации к System.gc
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. ... Вызов метода предлагает виртуальной машине Java приложить усилия для обработки неиспользуемых объектов, чтобы сделать память, которую они занимают, доступной для быстрого повторного использования. ....
В общем, это рекомендация, которая не гарантирует сборку мусора. Сборка мусора произойдет когда виртуальная машина посчитает нужным. Можете еще почитать ответ на вопрос: «Как часто надо вызывать сборщик мусора?»
Сборка мусора не обязательно освобождает память для ОС.
Даже если сборка мусора запустится, нет никакой гарантии, что освобожденная память будет возвращена ОС для использования в других процессах.
Освобождение памяти и выделение ее заново — ресурсоемкие задачи, которые могут оказать влияние на производительность клиентского (Вашего) кода. Поэтому разработчики JVM предусматривают сложные алгоритмы сборки мусора с минимальным влиянием на исполнение. В зависимости от настроек памяти JVM и используемого сборщика мусора память может быть сохранена для повторного использования Java (на очистку вообще не тратятся ресурсы) либо возвращена частично до определенного процентного порога (перераспределение памяти происходит в ограниченных масштабах).
Подробнее о разных сборщиках мусора смотрите в документации к используемой Вами версии JVM. Можете также ознакомиться с обзорными статьями по теме:
Статьи на сайте Oracle: Java HotSpot Garbage Collection Теория и практика Java: Сборка мусора в HotSpot JVM серия статей «Дюк, вынеси мусор!» на Хабре.

воскресенье, 14 апреля 2019 г.

Способы определить утечку памяти

Суть вопроса проста. Какие способы/инструменты есть для определения что память у нас утекла? ANSI C. Для Unix-подобных ОС x64-86 Нагуглил Hans Boehm garbage collector, но он то ли не работает с Linux x64, то ли я совсем его криво использую - всё время выдаёт 65536 на GC_get__heap_size(). crtdbg не подходит из-за привязки к MSVS. Изначально это была задача определить правильно ли я удаляю дерево, но переросло в этот вопрос.


Ответ

Попробуйте Valgrind. Одна из программ Valgrinda, Memcheck, насколько я понимаю, соответствует вашим требованиям.

понедельник, 25 февраля 2019 г.

Как использовать MAT с Android Studio?

Я установил MAT,выгрузил HEAP из Android Device Monitor и теперь у меня есть .hprof файл, как его проанализировать в MAT?


Ответ

Что бы конвертировать .hprof выгруженный из Android Studio в MAТобразный .hprof необходимо проделать следующие действия.
Открываем командную строку и идем в папку Android\sdk\platform-tool Затем вводим команду hprof-conv "путь к конвертируемому файлу" "путь к итоговому файлу" у меня это выглядело так:
C:\Users\sh_am\AppData\Local\Android\sdk\platform-tools> hprof-conv "C:\Users\sh_am\Desktop
ambotv30.hprof" "C:\Users\sh_am\Desktop\4mat.hprof"
Это создаст файл стандартный .hprof файл с именем которое вы указали у меня это 4mat.hprof
Открывал файл в MAT все работает отлично

пятница, 2 ноября 2018 г.

Вызовет ли realloc утечку памяти?

Доброго времени суток! Есть код:
// mry_char* - это wchar_t* // mry_charsz - это sizeof(wchar_t)
void mry_strcat(mry_char* _dest, const mry_char const* _src) { const u32 dl = mry_strlen(_dest); const u32 sl = mry_strlen(_src);
_dest = realloc(_dest, (dl + sl + 1) * mry_charsz); memmove(_dest + dl, _src, sl * mry_charsz); _dest[dl + sl] = '\0'; }
Cppcheck пишет:
Id: memleak Кратко: Memory leak: _dest Сообщение: Memory leak: _dest
First included by: mary.c
Строка 69: _dest[dl + sl] = '\0';
Я так понимаю, что утечка будет, если realloc переместит блок при возрастании размера, так ли это?
UPD
Исправил выход за границы массива.


Ответ

В своем коде вы должны рассчитывать на то, что realloc будет всегда перемещать блок, независимо от того, увеличивается ли его размер, уменьшается ли или вообще не меняется. Эти решения принимаются на основе неподконтрольных вам обстоятельств. То, что он может иногда и не переместиться - не более чем редкая и непредсказуемая удача.
Утечка у вас образуется из-за того, что новое значение указателя _dest в наружный код никак не возвращается. Память, выделенная вашим realloc в общем случае становится утечкой всегда. Либо возвращайте новый _dest из функции через возвращаемое значение, либо работайте с ним "по ссылке", т.е. делайте его mry_char** параметром.
(Да, если в результате работы realloc значение указателя _dest не изменилось, то формально возвращать его "не нужно", но ожидать этого в реальном коде - это полная белиберда. В общем случае значение указателя будет меняться.)
Дополнительно, в связи именно c realloc утечка также может возникнуть, если realloc не сможет выделить память вообще. Тогда он вернет null-указатель, но старую память не освободит, т.е. внутри функции доступ к памяти, изначально указываемой _dest, вы потеряете. (Будет ли это полноценной утечкой зависит от того, сохранили ли вы еще какой-то путь доступа к этой памяти. Из вашего кода этого не видно.)
Также, почему памяти выделяется только под dl + sl элементов, если потом делается _dest[dl + sl] = '\0'? Явный вылет за пределы выделенной памяти.