Подтвердить что ты не робот

Почему Go не имеет stackoverflows

Я прочитал в этой презентации http://golang.org/doc/ExpressivenessOfGo.pdf страница 42:

Safe

- переполнение стека

Как это возможно? и/или как работает Go, чтобы этого избежать?

4b9b3361

Ответ 1

Это функция, называемая "сегментированные стеки": каждый goroutine имеет свой собственный стек, выделен в куче.

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

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

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

Ответ 2

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

изменить:

Вот еще информация: http://golang.org/doc/go_faq.html#goroutines

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

Ответ 3

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

Когда память заканчивается, невозможно предотвратить переполнение стека.

Ответ 4

Даже C может сделать это с помощью нескольких ограничений, которые в основном влияют на компилятор.

Это впечатляющий ум, но не дизайн языка.

Ответ 5

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

Например:

package main

func main() {
    var a [10]int

    for i:= 0; i < 100; i++ {
        a[i] = i
    }
}

будет panic с ошибкой во время выполнения, когда он попытается обновить несуществующий 11-й элемент массива. C будет каракули над кучей и, вероятно, также рухнет, но неконтролируемым образом. Каждый массив знает свою длину. В некоторых случаях для компилятора будет возможность оптимизировать проверки, если он может доказать, что они не нужны. (Или достаточно умный компилятор, возможно, статически обнаруживает проблему в этой функции.)

Многие другие ответы говорят о макете памяти в стеке, но это действительно не актуально: вы можете также атаковать переполнение кучи.

В основном указатели Go всегда должны быть типов, с массивами и другими типами, если вы специально не используете пакет unsafe.