Переменные, хранящиеся в стеке, носят временный характер. Они принадлежат функции и т. Д., И когда функция возвращается и соответствующий кадр стека удаляется, переменные стека исчезают вместе с ней. Поскольку глобальные переменные предназначены для повсеместного доступа, они не должны выходить из контекста и поэтому хранятся в куче (или в специальном разделе данных двоичного файла), а не в стеке. То же самое касается static
переменных; поскольку они должны хранить свое значение между вызовами функции, они не могут исчезнуть при возврате функции, поэтому они не могут быть размещены в стеке.
Что касается защиты static
переменных, IIRC это в основном выполняется компилятором. Даже если переменная находится в куче, ваш компилятор знает ограниченный контекст, в котором эта переменная является допустимой, и любая попытка доступа к static
извне этого контекста приведет к «неизвестному идентификатору» или аналогичной ошибке. Единственный другой способ неверного доступа к переменной кучи - это если вы знаете адрес static
и слепо отмените ссылку на него. Это должно привести к ошибке доступа к памяти во время выполнения.
В многопоточной среде все еще можно использовать глобальные переменные и статические переменные. Тем не менее, вы должны быть намного осторожнее. Вы должны гарантировать, что только один поток может одновременно обращаться к переменной (обычно через какой-то механизм блокировки, такой как мьютекс). В случае static
локальных переменных внутри функции вы должны убедиться, что ваша функция будет по-прежнему функционировать так, как ожидается, если она вызывается из нескольких потоков последовательно (то есть вызывается из потока 1, затем из потока 2, затем потока 1, потом нить 2 и тд и тп). Это обычно труднее сделать, и многие функции, которые полагаются на static
переменные-члены, не являются поточно-ориентированными из-за этого (strtok
является ярким примером).