Глобальные переменные используют много памяти arduino

Обновлено: 06.07.2024

Здравствуйте!
Возникли подозрения, что не хватает оперативной памяти.

В документации на ардуино написано, что ОЗУ и стек располагаются рядом. ОЗУ заполнятся слева направо, стек справа налево. Могут возникать ситуации наезда ОЗУ на стек или наоборот.

Возможно ли через «Serial.print()» или каким либо другим образом оперативно выводить, сколько использовано ОЗУ или сколько осталось свободной и наезжает ли ОЗУ на стек?

И не могу найти информацию, сколько ОЗУ занимает char и String.
Например «char st2[0]="00 01 02 03 04 05 06 07"» и «String st2[0]="00 01 02 03 04 05 06 07»?

Перессылка массива данных из одного места ОЗУ в другое место ОЗУ
Есть ли какой-нибудь примерчик программки, которая выполняет пересылку массива данных размерностью.

Что будет если в 1 слот поставить 2 ОЗУ. Получится ли задублировать ОЗУ?
В теории. Например две одинаковые планки? Зачем? Любопытство, ну и есть кое какие мысли по этому).

Какой эффект будет если к ПК с 1024 мб ОЗУ, процессор одноядерный добавить 1-2 гб ОЗУ
Какой эффект будет если к ПК с 1024 мб ОЗУ, 2.1гц, Ram 512, проц.(одноядерный) добавить 1-2 гб.

Перестали работать вместе озу. Все слоты рабочие, проверял другой озу
Проблемы с 2-мя плашками по 4gb, которые начали отказывать работать вместе. Есть подозрения на биос.

массив из 0 элементов
пишешь в чужую память
вот так попробуй

Неверно поставил вопрос.
Пишу «char * st2[20];», компилирую, замеряю размер скетча.
Дописываю «st2[0]="00 01 02 03 04 05 06 07";» - размер скетча увеличился на 32 байта, а по идее должен увеличиться на 23 байта.

Делаю тоже самое, только со «String st2[20];». Размер скетча увеличивается на 36 байт!
Но у меня строки массива задаются НЕ заранее, а определяются в момент выполнения программы.
С размером массива до 7 все работает, но мне нужен массив из 20 строк (каждая до 23х байт).
Вот я и хочу посмотреть, что твориться в оперативной памяти.

Сергей 190, Указывайте компилятор
Из исходных данных для моего IAR я проблем не вижу, но другие компиляторы могут .

Витальич навел меня на мысль. Я пользовался версией «1.5.2». После компиляции выводился только размер скетча.
Скачал версию «1.6.4». Появилась информация об ОЗУ.
Показало, что глобальные переменные занимают 1 891 байт, осталось 157.
Объявленных переменных не так уж и много, стал разбираться.

Выяснилось, следующее:
Serial.print(переменная) увеличивает только размер скетча на 12 байт.
Serial.print("текст") увеличивает и размер скетча, и место в оперативной памяти.

Serial.print("текст") у меня многовато и съели больше половины ОЗУ.
Решил вызывать нужные тексты из файла на SD карте.

Вызов процедуры Print(P,znak); где znak – номер строки из файла, которую нужно вывести на экран и если P==1 перевести на следующую строку.

Первый вызов процедуры увеличил размер скетча на 1224 байта и ОЗУ на 12 байт.
Последующие вызовы увеличивает только размер скетча на 16 байт.

Написал в лоб. Может, кто подскажет более красивое решение?

Но эта информация ДО выполнения программы.
Вопрос «можно ли оперативно выводить, сколько использовано ОЗУ в каждый момент во время выполнения программы?» остаётся актуальным.

в IAR которым пользуется Витальич есть отладчик. в моем компиляторе есть отладчик. в них можно посмотреть сколько памяти занято, где занято. мой компилятор при переполнении памяти выдает ошибку.
а ардуино похоже пофигу. вот что будет если файл на SD превысит объем ОЗУ? Вызов процедуры Print(P,znak); где znak – номер строки из файла, тебе же это только для отладки нужно. сделай Print(znak); а на листе бумаги напиши, что каждый знак обозначает. при ошибке можеш число с минусом выводить(так удобней).
можно ли оперативно выводить, сколько использовано ОЗУ ИМХО, нельзя. МК не любят динамические переменные(динамически изменяемые массивы). размер занятой ОЗУ определяется при компиляции.
размер стека меняется. на ассемблере можно посмотреть последний адрес в стека. и записать туда чего нибуть и программа зависнет. 1. Для С++
Классический компилятор создаст в ОЗУ переменные int P и int Ns, что вызовет увеличении размера ОЗУ
Создаст указатели на эти переменные.
Посмотрите, что меньше "съест" ОЗУ
ИМХО: для восьмибитника скорей всего будет по барабану.
2. А Вам так важно использовать int, я стараюсь брать тип как можно меньшей размерности если данные гарантировано не превысят размерности типа.
Вопрос «можно ли оперативно выводить, сколько использовано ОЗУ в каждый момент во время выполнения программы? не знаю как у Вас, но в IAR можно посмотреть таблицу размещения переменных в памяти, а также задавать размер стека. По динамическим переменным, согласен с уважаемым Grey.
Также попробуйте поиграться настройками оптимизации.
P.S. Насколько помню (давно не попадал в такие ситуации), IAR не отслеживает ошибки связанные с переполнением ОЗУ и обнаружить её можно только во время отладки. в IAR которым пользуется Витальич есть отладчик. в моем компиляторе есть отладчик Витальич, у Вас какой компилятор? Grey, а Вы каким пользуетесь?
И вообще, что такое отладчик? Где его брать и как им пользоваться?
в IAR можно посмотреть таблицу размещения переменных в памяти, а также задавать размер стека Нельзя ли поподробнее. Может ссылки какие, что бы почитать.
Я пользуюсь IAR (яры есть почти под все платформы МК, что позволяет с минимальным переучиванием переходить на разные контроллеры). Но Вам это не поможет, выбрав ардуину, которая по сути является программно аппаратным законченным решением, Вы только этой средой и можете пользоваться, можно еще взять Atmel Studio, но там для новичка еще печальней всё выглядит.
Это программный или программно-аппаратный модуль, который позволяет просмотреть внутреннее состояние МК (контекст МК) в любой момент времени. Моменты времени выбираются заданными точками останова или пошаговым выполнением программы.
Можно, но знания по IAR (самая не любимая среда большинства программистов МК, да еще при этом и самая дорогая ) Вам не помогут, он слишком сильно отличается от ардуины, а ардуиной я вообще не занимался так что извините.
К примеру вот так в IAR выглядит отладчик (окно напихал от фонаря, обычно столько не нужно) Algorithm Builder 5.44
довольно удобный. если умееш строить алгоритмы, то и очень понятный.
в сети можно найти примеры кодов к нему. но готовых библиотек в нём нету.
и это всё таки ассемблер.
так, что не советую. симулятор, отладчик в AB. там ещё много чего можно открыть. однако, в комплекте Arduino IDE уже идёт WinAVR (\hardware\tools\avr\), поэтому можно воспользоваться им. в WinAVR был отладчик. но в ардуино(по крайне мере последней версии) WinAVR не полностью, не весь комплект программ. но можно попробовать востановить.

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

Добавлено через 8 минут
Ардуиновский String в оперативной памяти занимает 2байта на указатель, 2байта на размер зарезервированной области, 2байта на размер данных, 2байта на предзаголовок блока пвыделеленной памяти и плюс сами данные с терминирующим нулем.

Добавлено через 2 минуты
Для решения проблемы хранения строк в оперативной памяти, ардуиновские либы обучены работать с флеш строками. Можно использовать их.

Добавлено через 4 минуты
Самый простой, но малоточный способ оценки имеющийся памяти состоит в сравнении текущий вершины кучи __brkval (не помню, как то так он называется) и указателя стека (SP).

Игры используют только 1 плашку озу,то есть загружают под 50 % озу а 2 плашка отдыхает
Тип ЦП QuadCore Intel Core i5-7500, 3600 MHz (36 x 100) Системная плата Asus H110M-R (2 PCI-E x1.

Не запускается виндовс после установки второй планки озу 1333mhz к озу 1600mhz (ddr3)
После установки 2й планки памяти ddd3 1333mhz к ddr3 1600mhz (обе по 4гб, обе good ram) комп выдал.

Комп не работает с ОЗУ, раньше работал. ОЗУ рабочая
Дело было так. На компе стоит 8Гб озу(2 планки по 4Гб). Раньше комп работал без изъянов. Утром.

ОЗУ 800Mhz не работает с ОЗУ 667Mhz, зависает комп
ОЗУ 1Gb 800Mhz не работает с ОЗУ 1Gb 667Mhz, зависает комп, сказали что надо в биосе что то.

Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно.
Вам необходимо обновить браузер или попробовать использовать другой.

Андрей 2704

В чём может быть проблема ? Выдаёт такую ошибку :
Arduino: 1.8.10 (Windows 10), Плата:"ATmega328 based, internal 8 MHz, disable, enable, Without bootloader, enable, default Serial, disable, enable, default v5.4.0"

In file included from C:\Users\Андрей\Desktop\SDreader-master\firmware\SDreader_v1.0\SDreader_v1.0.ino:29:0:

Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
"Показать подробный вывод во время компиляции"

Старик Похабыч

DrFly

При прошивке надо отключать RX и TX блютуза от Ардуины. Спасибо. Уже ищу коннектор, чтобы не паять туда сюда.
Вопрос еще возник, прочитал, по форуму, но так и не понял в чем проблема: управление играми через блютуз, кнопки в приложении, как-то произвольно направление движения выбирают. Это проблема с кодом прошивки или недаработка в приложении, или надо как то особо управлять просто.

xGTZx

Доброго времени суток. я только начал знакомиться с ардуино, использую Arduino Nano, сделал вроде все как по инструкции выдало ошибку:

avrdude: stk500_recv(): programmer is not responding
avrdude: verification error, first mismatch at byte 0x0000
0xff != 0x0c
avrdude: verification error; content mismatch
avrdude: verification error; content mismatch

В Инструментах все выставлено паралельно вроде.
Подскажите куда копать, где я допустил ошибку? Заранее спасибо.

Вложения

Безымянный.jpg

Krotaz

Arduino: 1.8.8 (Windows 7), Плата:"Arduino Nano, ATmega328P"

Wan-Derer

@xGTZx, возможно, что-то подключено к линиям tx/rx. Во время прошивки они должны быть свободны

xGTZx

@xGTZx, возможно, что-то подключено к линиям tx/rx. Во время прошивки они должны быть свободны К плате ничего не подключено.
Вот подробный отчет по загрузке, пойду куплю другой провод может дело в проводе.

Вложения

Wan-Derer

xGTZx

На чипе написано Atmel MEGA 328P V-TH 354 730 1935WPB
Купил другую плату и вреде все прошилось, видно брак попался.

Wan-Derer

@xGTZx, Тогда непонятно. Сигнатура читается, значит Мега видна. Но не прошивается. Пробуй другой кабель и другую Ардуино.

xGTZx

@xGTZx, Тогда непонятно. Сигнатура читается, значит Мега видна. Но не прошивается. Пробуй другой кабель и другую Ардуино. Уже попробовал другую Ардуину прошилось.
меня смущает еще тот нюанс что у первой индикатор PWR светиться красным постоянно.

Wan-Derer

@xGTZx, Посмотри её под микроскопом на предмет непропая/соплей

Igor100

Всем доброго времени суток. Просьба о помощи. Не могу загрузить скетч в ардуино UNO. Собщение об ошибке:
Arduino: 1.6.7 (Windows 8), Плата:"Arduino Uno"

Arduino: 1.6.7 (Windows 8), Плата:"Arduino Uno"

Скетч использует 922 байт (2%) памяти устройства. Всего доступно 32 256 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2 039 байт для локальных переменных. Максимум: 2 048 байт.
avrdude: ser_open(): can't open device "\\.\COM2935": Не удается найти указанный файл.

Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\______1_______________________: C:\Users\Игорь\Documents\Arduino\libraries\______1_______________________
Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\_________________: C:\Users\Игорь\Documents\Arduino\libraries\_________________
Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\_2__________________________FOR: C:\Users\Игорь\Documents\Arduino\libraries\_2__________________________FOR
Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\_3: C:\Users\Игорь\Documents\Arduino\libraries\_3
Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\______1_______________________: C:\Users\Игорь\Documents\Arduino\libraries\______1_______________________
Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\_________________: C:\Users\Игорь\Documents\Arduino\libraries\_________________

Александр Симонов

Всем доброго времени суток. Просьба о помощи. Не могу загрузить скетч в ардуино UNO. Собщение об ошибке:
Arduino: 1.6.7 (Windows 8), Плата:"Arduino Uno"

Arduino: 1.6.7 (Windows 8), Плата:"Arduino Uno"

Скетч использует 922 байт (2%) памяти устройства. Всего доступно 32 256 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2 039 байт для локальных переменных. Максимум: 2 048 байт.
avrdude: ser_open(): can't open device "\\.\COM2935": Не удается найти указанный файл.

Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\______1_______________________: C:\Users\Игорь\Documents\Arduino\libraries\______1_______________________
Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\_________________: C:\Users\Игорь\Documents\Arduino\libraries\_________________
Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\_2__________________________FOR: C:\Users\Игорь\Documents\Arduino\libraries\_2__________________________FOR
Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\_3: C:\Users\Игорь\Documents\Arduino\libraries\_3
Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\______1_______________________: C:\Users\Игорь\Documents\Arduino\libraries\______1_______________________
Неверная библиотека найдена в C:\Users\Игорь\Documents\Arduino\libraries\_________________: C:\Users\Игорь\Documents\Arduino\libraries\_________________

Согласно документации Arduino, ATmega328 имеет 32 КБ флэш-памяти для загрузчика + загруженный эскиз и только 2 КБ SRAM для данных времени выполнения. ATmega2560 имеет немного больше, общий объем 256 КБ и 8 КБ соответственно.

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

Что вы можете сделать, если у вас кончились? Например, если ваш эскиз слишком большой или вам нужно обрабатывать много данных (например, строк) во время выполнения? Есть ли способ расширить Flash или SRAM?

Попробуйте использовать некоторые переменные оптимизации. Некоторые различные переменные обсуждаются здесь Используйте надлежащие области действия для ваших переменных, если это еще не сделано, компилятор оптимизирует использование оперативной памяти для вас, когда переменные не используются. Вы можете использовать Teensy 3.2 (с программным обеспечением Teensyduino), которое будет сравнимо с Arduino. Учитывая, что у вас заканчивается RAM / PROGMEM, это также означает, что вы, скорее всего, пытаетесь подтолкнуть Arduino. Teensy 3.2 не намного дороже. но имеет: 32-битную, 72 МГц (wtf !?) флэш-память 256 КБ, 64 КБ ОЗУ и 3x UART. Не больше памяти программ, как у ATmega2560, но должно быть достаточно оперативной памяти и увеличения скорости.

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

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

Иногда также полезно определить, где несколько частей вашего кода одинаковы (или очень похожи). Вы можете сжать их в многократно используемые функции, которые можно вызывать из нескольких мест. Однако имейте в виду, что иногда попытка сделать код слишком многократно используемым на самом деле делает его более многословным. Это сложный баланс для забастовки, который имеет тенденцию приходить с практикой. Можно потратить некоторое время на изучение того, как изменения кода влияют на вывод компилятора.

Оптимизация данных времени выполнения (SRAM) имеет тенденцию быть немного легче, когда вы к этому привыкли. Очень распространенная ловушка для начинающих программистов - использование слишком большого количества глобальных данных. Все, что объявлено в глобальном масштабе, будет существовать в течение всего времени существования эскиза, и это не всегда необходимо. Если переменная используется только внутри одной функции, и она не должна сохраняться между вызовами, то сделайте ее локальной переменной. Если значение должно быть разделено между функциями, подумайте, можете ли вы передать его как параметр вместо того, чтобы делать его глобальным. Таким образом, вы будете использовать SRAM только для тех переменных, которые вам действительно нужны.

Еще одним убийцей использования SRAM является обработка текста (например, использование String класса). Вообще говоря, вам следует избегать выполнения операций со строками, если это возможно. Они огромные боровы памяти. Например, если вы выводите много текста в последовательный порт, используйте несколько вызовов Serial.print() вместо вместо конкатенации строк. Также попытайтесь сократить количество строковых литералов в вашем коде, если это возможно.

Избегайте рекурсии, если это возможно. Каждый раз, когда выполняется рекурсивный вызов, стек поднимается на уровень глубже. Перефразируйте ваши рекурсивные функции, чтобы они стали итеративными.

Использование EEPROM
EEPROM используется для долговременного хранения вещей, которые изменяются только изредка. Если вам нужно использовать большие списки или справочные таблицы с фиксированными данными, подумайте о том, чтобы заранее сохранить их в EEPROM и извлекать только то, что вам нужно, когда это необходимо.

Очевидно, что EEPROM довольно ограничен по размеру и скорости и имеет ограниченное количество циклов записи. Это не лучшее решение для ограничения данных, но этого может быть достаточно, чтобы облегчить нагрузку на Flash или SRAM. Также возможно взаимодействие с аналогичным внешним хранилищем, таким как SD-карта.

Расширение
Если вы исчерпали все остальные варианты, возможно, расширение возможно. К сожалению, расширение флэш-памяти для увеличения места в программе невозможно. Тем не менее, есть возможность расширить SRAM. Это означает, что вы сможете реорганизовать свой эскиз, чтобы уменьшить размер кода за счет увеличения размера данных.

Получить больше SRAM на самом деле довольно просто. Один из вариантов - использовать один или несколько чипов 23K256 . Доступ к ним осуществляется через SPI, и есть библиотека SpiRAM, которая поможет вам их использовать. Просто знайте, что они работают при 3,3 В, а не 5 В!

Если вы используете Mega, вы также можете получить щиты расширения SRAM от Lagrangian Point или Rugged Circuits .

Глобальная переменная в Arduino – это переменная, область видимости которой распространяется на всю программу, ее видно во всех модулях и функциях. В этой статье мы рассмотрим несколько примеров использования глобальных переменных, а также поговорим о том, когда нужно использовать глобальную переменную, а когда лучше не стоит

Область видимости переменных в Arduino

Как мы хорошо знаем, в любом языке программирования переменные служат для хранения каких-либо данных. У каждой переменной есть название и тип, а для создания переменной надо просто указать вместе и то и другое. Например, написав в коде “int sum;” мы укажем компилятору, что нужно создать ячейку памяти с типом данных int и названием sum.

Создав переменную, мы можем использовать ее для сохранения и считывания значений. Но остается вопрос – где именно мы можем это сделать? Согласно правилам Arduino (на самом деле, эти правила заложены в основу C++), у каждой переменной есть свой ареал обитания – область, где с ней можно работать, т.е. сохранять значения и считывать их. И программист должен обязательно понимать, где заканчивается эта область.

Локальные переменные

Локальные переменные – это переменные, область видимости которых ограничена текущим, «локальным», блоком. Например, мы можем определить переменную в блоке, ограниченном операторами if (условия) и переменная будет видна только внутри. Примеры локальных блоков:

  • Внутри цикла (for, while)
  • Внутри функции
  • Внутри блока условия (if, else).

Ограниченность означает следующее: компилятор позволит использовать название переменной внутри блока, но «не узнает» ее, если мы обратимся извне. Давайте посмотрим пример:

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

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

Мы обратились к переменной, взяли ее значение и отправили в монитор порта в функции Serial.println.

А давайте попробуем написать другую функцию и попробуем вывести это значение оттуда. Получится ли у нас это?

Конечно же, нет. В функции calculator компилятор попытается найти определение переменной internalSum внутри функции, но не найдет его (мы же определили internalSum совсем в другой функции, sum()). Расстроившись от этого, компилятор выдаст ошибку (на самом деле, возможность ее избежать и есть использование глобальных переменных – об этом как раз и расскажем позже). Таким образом, мы можем что угодно делать с переменной в своем блоке, но ничего не можем сделать в другом.

Такое поведение компилятора не случайно и легко объяснимо. Зачем нам использовать переменную и данные в области, где их не нужно обрабатывать? Если мы в другом месте случайно изменим значение переменной (глобальной переменной), которую используем в этом месте, то можем создать множество трудноуловимых ошибок. Компилятор защищает нас от этого, просто запрещая использование название переменной из другой области, если это не требуется. К тому же фантазия человека ограничена и нам будет трудно придумать множество названий глобальных переменных так, чтобы они были понятны и не пересекались.

Глобальная переменная

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

Если блок находится внутри текущего (например, внутри функции есть блок с циклом), то в нем будут видны значения из «внешнего» блока. Например, в данном примере внутри блока for мы можем замечательно видеть и использовать переменную result:

Второй вариант – использовать глобальную переменную.

Глобальная переменная – это переменная, область видимости которой не ограничена рамками отдельных функций или внутренних блоков. Мы можем использовать и изменять глобальную переменную в любом месте в программе и компилятор не будет при этом против.

Давайте рассмотрим следующий пример скетча arduino:

Мы используем глобальные переменные для того, чтобы хранить значения между вызовами функции loop, а также для того, чтобы не писать несколько раз номер пина (глобальная переменная pinLed используется в качестве константы). Переменная lastMills нужна для реализации работы части функционала без использования delay().

Глобальные переменные arduino– возможные проблемы

О возможных проблемах использования глобальных переменных мы уже говорили. Обладая возможностью менять значение переменной в любом месте, мы можем совершить ошибку, случайно изменив значение в самых разных местах программы. И нам придется просмотреть всю нашу программу, выискивая все случаи использования глобальной переменной. Нам придется постоянно держать в голове, как отразятся изменения глобальной переменной, которые мы делаем в одном месте на остальные части программы. И это действительно большая проблема для больших проектов.

Другой специфичной проблемой использования глобальных переменных arduino является память. Как известно, в контроллерах Arduino не то что не ограниченное, а как раз очень сильно ограниченное количество памяти. В реальных проектах может вестись борьба практически за каждый байт. Локальные переменные создаются динамически и исчезают из памяти после завершения выполнения функции, освобождая память. А как тут ведут себя глобальные переменные? А ведут они себя очень плохо. Т.к. их значения должны быть доступны повсюду, то они постоянно висят в памяти, не освобождая ее. И если глобальных переменных в коде много, то и памяти под них в итоге требуется тоже немало, что может привести к проблемам.

Читайте также: