HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-21
1 <p><a>#статьи</a></p>
1 <p><a>#статьи</a></p>
2 <ul><li>29 июн 2020</li>
2 <ul><li>29 июн 2020</li>
3 <li>0</li>
3 <li>0</li>
4 </ul><p>Разбираемся в трудно уловимых уязвимостях приложений, чтобы всё работало гладко и без тормозов.</p>
4 </ul><p>Разбираемся в трудно уловимых уязвимостях приложений, чтобы всё работало гладко и без тормозов.</p>
5 <p> vlada_maestro / shutterstock</p>
5 <p> vlada_maestro / shutterstock</p>
6 <p>Пишет о программировании, в свободное время создаёт игры. Мечтает открыть свою студию и выпускать ламповые RPG.</p>
6 <p>Пишет о программировании, в свободное время создаёт игры. Мечтает открыть свою студию и выпускать ламповые RPG.</p>
7 <p><strong>Утечка памяти</strong><em>(англ.<strong>memory leak</strong>)</em> - это неконтролируемое уменьшение свободной оперативной или виртуальной памяти компьютера. Причиной утечек становятся ошибки в программном коде.</p>
7 <p><strong>Утечка памяти</strong><em>(англ.<strong>memory leak</strong>)</em> - это неконтролируемое уменьшение свободной оперативной или виртуальной памяти компьютера. Причиной утечек становятся ошибки в программном коде.</p>
8 <p>В этой статье мы поймём, как появляются утечки и как их устранять.</p>
8 <p>В этой статье мы поймём, как появляются утечки и как их устранять.</p>
9 <p>Любые программы используют в своей работе память, чтобы<a>хранить какие-то данные</a>. В C++ и многих других языках память динамическая. Это значит, что операционная система при запуске программы резервирует какое-то количество ячеек в ОЗУ, а потом выделяет новые, если они нужны.</p>
9 <p>Любые программы используют в своей работе память, чтобы<a>хранить какие-то данные</a>. В C++ и многих других языках память динамическая. Это значит, что операционная система при запуске программы резервирует какое-то количество ячеек в ОЗУ, а потом выделяет новые, если они нужны.</p>
10 <p>Создали переменную для числа<em>(int)</em>? Вот тебе 16 бит<em>(4 байта)</em>. Нужен массив из ста элементов для больших чисел<em>(long)</em>? Вот тебе ещё 3200 бит<em>(800 байт)</em>.</p>
10 <p>Создали переменную для числа<em>(int)</em>? Вот тебе 16 бит<em>(4 байта)</em>. Нужен массив из ста элементов для больших чисел<em>(long)</em>? Вот тебе ещё 3200 бит<em>(800 байт)</em>.</p>
11 <p>Когда программисту уже не нужен какой-то массив или объект, он должен сказать системе, что его можно удалить с помощью<a>оператора delete[]</a>и освободить память.</p>
11 <p>Когда программисту уже не нужен какой-то массив или объект, он должен сказать системе, что его можно удалить с помощью<a>оператора delete[]</a>и освободить память.</p>
12 //Создаём пустой указатель double *pointer; //Создаём массив и получаем ссылку на него pointer = new double[15]; //Указываем тестовое значение для первой ячейки pointer[0] = 5; //Выведет адрес ячейки и 5, так как по адресу находится первый элемент массива cout &lt;&lt; "Address: " &lt;&lt; pointer &lt;&lt; " | Value: " &lt;&lt; *pointer &lt;&lt; "\n"; delete [] pointer; cout &lt;&lt; "Deleted\n"; //Адрес остался прежним, но значение будет 0, так как память была очищена cout &lt;&lt; "Address: " &lt;&lt; pointer &lt;&lt; " | Value: " &lt;&lt; *pointer &lt;&lt; "\n";<p>Вот результат:</p>
12 //Создаём пустой указатель double *pointer; //Создаём массив и получаем ссылку на него pointer = new double[15]; //Указываем тестовое значение для первой ячейки pointer[0] = 5; //Выведет адрес ячейки и 5, так как по адресу находится первый элемент массива cout &lt;&lt; "Address: " &lt;&lt; pointer &lt;&lt; " | Value: " &lt;&lt; *pointer &lt;&lt; "\n"; delete [] pointer; cout &lt;&lt; "Deleted\n"; //Адрес остался прежним, но значение будет 0, так как память была очищена cout &lt;&lt; "Address: " &lt;&lt; pointer &lt;&lt; " | Value: " &lt;&lt; *pointer &lt;&lt; "\n";<p>Вот результат:</p>
13 <a></a><p>Однако иногда случаются ошибки, которые приводят к утечкам памяти. Вот одна из них:</p>
13 <a></a><p>Однако иногда случаются ошибки, которые приводят к утечкам памяти. Вот одна из них:</p>
14 <a></a><p>На примере в цикле десять раз создаётся новый массив, а его адрес записывается в указатель. Адреса старых массивов при этом удаляются. Поэтому дальше оператор<em>delete[]</em>удаляет только последний созданный массив. Остальные останутся в памяти до тех пор, пока не будет закрыта программа.</p>
14 <a></a><p>На примере в цикле десять раз создаётся новый массив, а его адрес записывается в указатель. Адреса старых массивов при этом удаляются. Поэтому дальше оператор<em>delete[]</em>удаляет только последний созданный массив. Остальные останутся в памяти до тех пор, пока не будет закрыта программа.</p>
15 <p>Когда приложение съест всю доступную память, сработает защита ОС и ваша программа аварийно закроется. Однако у утечек могут быть и более опасные последствия.</p>
15 <p>Когда приложение съест всю доступную память, сработает защита ОС и ваша программа аварийно закроется. Однако у утечек могут быть и более опасные последствия.</p>
16 <p>Например, приложение может работать с каким-нибудь файлом непосредственно перед закрытием. В этом случае файл будет повреждён. Последствия возможны самые разные: от нервного срыва пользователя, если это была презентация, над которой он работал несколько дней, до поломки системы, если это был очень важный файл.</p>
16 <p>Например, приложение может работать с каким-нибудь файлом непосредственно перед закрытием. В этом случае файл будет повреждён. Последствия возможны самые разные: от нервного срыва пользователя, если это была презентация, над которой он работал несколько дней, до поломки системы, если это был очень важный файл.</p>
17 <p>В отдельных случаях утечка памяти одного приложения может привести к последствиям для других работающих приложений. Например, если ваш код изменил или занял память, используемую другой программой.</p>
17 <p>В отдельных случаях утечка памяти одного приложения может привести к последствиям для других работающих приложений. Например, если ваш код изменил или занял память, используемую другой программой.</p>
18 <p>Может показаться, что раз это "утечка", то что-то случится с вашими данными. На самом деле утекает именно свободная память, а не её содержимое.</p>
18 <p>Может показаться, что раз это "утечка", то что-то случится с вашими данными. На самом деле утекает именно свободная память, а не её содержимое.</p>
19 <p>Если у вас есть доступ к исходникам, то изучите код, чтобы определить, нет ли там утечек. Вручную делать это бессмысленно, особенно если проект большой, поэтому обратимся к <strong>отладчику использования памяти</strong><em>(англ.<strong>memory debugger</strong>).</em></p>
19 <p>Если у вас есть доступ к исходникам, то изучите код, чтобы определить, нет ли там утечек. Вручную делать это бессмысленно, особенно если проект большой, поэтому обратимся к <strong>отладчику использования памяти</strong><em>(англ.<strong>memory debugger</strong>).</em></p>
20 <p>Если вы пользуетесь IDE вроде Visual Studio, то там должен быть встроенный отладчик. Есть и сторонние инструменты вроде<a>GDB</a>или<a>LLDB</a>. Отладчик покажет, какие данные хранит программа и к каким ячейкам имеет доступ.</p>
20 <p>Если вы пользуетесь IDE вроде Visual Studio, то там должен быть встроенный отладчик. Есть и сторонние инструменты вроде<a>GDB</a>или<a>LLDB</a>. Отладчик покажет, какие данные хранит программа и к каким ячейкам имеет доступ.</p>
21 <p>И будьте осторожнее с указателями:</p>
21 <p>И будьте осторожнее с указателями:</p>
22 <a></a><em>Указатель на указатель на указатель на переменную X</em><p>Если доступа к коду у вас нет, но нужна библиотека, в которой есть утечка, то её стоит вынести в отдельную программу<em>(B)</em>. Ваша основная программа<em>(A)</em>запустит программу B, чтобы вызвать какую-то функцию. После этого программа B будет закрываться, чтобы освободить всю использованную<em>(в том числе и утёкшую)</em>память.</p>
22 <a></a><em>Указатель на указатель на указатель на переменную X</em><p>Если доступа к коду у вас нет, но нужна библиотека, в которой есть утечка, то её стоит вынести в отдельную программу<em>(B)</em>. Ваша основная программа<em>(A)</em>запустит программу B, чтобы вызвать какую-то функцию. После этого программа B будет закрываться, чтобы освободить всю использованную<em>(в том числе и утёкшую)</em>память.</p>
23 <p>Если же функционал из библиотеки нужен постоянно, то программу B можно оставить работать, но перезапускать её с определённой периодичностью - до того как она сожрёт слишком большой объём памяти.</p>
23 <p>Если же функционал из библиотеки нужен постоянно, то программу B можно оставить работать, но перезапускать её с определённой периодичностью - до того как она сожрёт слишком большой объём памяти.</p>
24 <p>Конечно, лучше избегать таких библиотек, но мы живём в неидеальном мире - иногда альтернатив попросту нет.</p>
24 <p>Конечно, лучше избегать таких библиотек, но мы живём в неидеальном мире - иногда альтернатив попросту нет.</p>
25 <p>В более высокоуровневых языках вроде C# или Java существуют<strong>сборщики мусора</strong><em>(англ.<strong>garbage collector</strong>)</em>. Это специальный процесс, который сканирует память и удаляет те ячейки, которые уже не нужны приложению.</p>
25 <p>В более высокоуровневых языках вроде C# или Java существуют<strong>сборщики мусора</strong><em>(англ.<strong>garbage collector</strong>)</em>. Это специальный процесс, который сканирует память и удаляет те ячейки, которые уже не нужны приложению.</p>
26 <p>В C++ сборщика мусора нет, поэтому приходится следить за памятью самостоятельно. Это требует более высокой квалификации разработчика, но позволяет увеличить скорость работы приложений.</p>
26 <p>В C++ сборщика мусора нет, поэтому приходится следить за памятью самостоятельно. Это требует более высокой квалификации разработчика, но позволяет увеличить скорость работы приложений.</p>
27 <p>Впрочем, иногда от утечек не спасает и сборщик мусора.</p>
27 <p>Впрочем, иногда от утечек не спасает и сборщик мусора.</p>
28 <p>Такие проблемы всегда сложно искать в коде, поэтому они встречаются так часто и поэтому многие приложения виснут и вылетают.</p>
28 <p>Такие проблемы всегда сложно искать в коде, поэтому они встречаются так часто и поэтому многие приложения виснут и вылетают.</p>
29 <a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>
29 <a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>