2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3, 4  След.
 
 Re: Что такое аппаратный стек
Сообщение31.05.2018, 10:36 
Заслуженный участник
Аватара пользователя


30/01/06
72407
arseniiv в сообщении #1316433 писал(а):
Но приоритеты надо тоже расставлять.

Разумеется. Это сведения не для первого знакомства, но для профессионального разработчика. Занимающегося производительностью, переносимостью, поддержкой сложной системы, и т. п. задачами. Сведения примерно того же уровня, что и оценки сложности используемых библиотечных структур данных и алгоритмов.

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение31.05.2018, 14:04 
Заслуженный участник


20/08/14
11763
Россия, Москва
iakovk в сообщении #1316434 писал(а):
Если вы считаете, что я здесь неправ, укажите конкретно, в чем.
Вы правы, но осветили лишь одну сторону проблемы, переполнение виртуальных адресов, а есть ещё и переполнение физической памяти (вместе с файлом подкачки). И если пример успешного выделения в стеке более миллиона терабайтов, что намного превышает размер памяти вместе с файлом подкачки (впрочем аналогичное можно проделать и на x86 системе, только описать совокупность условий сложнее), Вас не убеждает, то мне добавить нечего.

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение31.05.2018, 14:30 
Заслуженный участник
Аватара пользователя


01/08/06
3128
Уфа
Кстати, архитектура x86-64 поддерживает только 256 терабайт виртуального адресного пространства, а в Win64, например, процессу и вовсе доступны какие-то жалкие :D 8 терабайт (ну может быть, 16). Так что тут всё равно непонятно, как виртуальные адреса не переполнились при выделении миллиона терабайт. Возможно, виртуальная машина http://www.cpp.sh/ работает на какой-то другой архитектуре.

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение31.05.2018, 20:47 
Аватара пользователя


07/02/12
1433
Питер
Munin в сообщении #1316346 писал(а):
Тогда почему бы стек не начинать с адреса 0xFFFFFFFFFFFFFFFC? И не было бы никакого ограничения в 1 Мб.
Раньше, кстати, так и делали (с поправкой на разрядноcь адресов). Можно просто с нуля - при росте стека его значение сначала уменьшается, потом заполняется данными.

Именно это и является причиной того, что стек в x86/64 (и ARM) растет сверху вниз: снизу ели память данные программы, сверху - стек. Этот атавизм сохранился до сих пор, хотя уже больше 20 лет, с появлением вытесняющей многозадачности и необходимостью размещать несколько стеков одновременно, принципиально перестал быть полезным.

Впрочем, пробегали несколько извращенные подходы использования атавизма - например, последовательное чтение данных из массивов командами pop (это оказывалось быстрее классических способов).

Dmitriy40 в сообщении #1316217 писал(а):
Конкретно в данном случае вмешивается ОС с механизмом подкачки виртуальных страниц, т.е. память-то выделяется (в x64 ОС), но не физическая, а виртуальная, и физически существуют лишь те страницы памяти, в которые была реальная запись
Скорее, вообще никакая не выделяется. Точнее, выделяется она, если так можно сказать, в момент создания потока. В момент входа в такую экзотическую функцию просто уменьшается значение стека, перепрыгнув кучу страниц. Пока это значение не выйдет за пределы допустимой области, или массив не начнет реально использоваться, никто ничего не заметит.

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение01.06.2018, 12:18 


27/08/16
10195
bondkim137 в сообщении #1316593 писал(а):
В момент входа в такую экзотическую функцию просто уменьшается значение стека, перепрыгнув кучу страниц. Пока это значение не выйдет за пределы допустимой области, или массив не начнет реально использоваться, никто ничего не заметит.
Не совсем так. В момент входа в функцию с очень большим расходом стека проверяется, что стек не переполнится. Для функций с маленьким расходом стека (меньше страницы) такая проверка излишняя, так как за границей выделенного стека размещают одну дополнительную защитную страницу для детектировани его переполнения.

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение01.06.2018, 12:39 
Заслуженный участник


20/08/14
11763
Россия, Москва
realeugene в сообщении #1316672 писал(а):
Не совсем так. В момент входа в функцию с очень большим расходом стека проверяется, что стек не переполнится.
Не совсем так (С). Когда размер требуемого стека больше страницы, то он не проверяется, а инициализируется, чтобы все страницы были реально выделены. Вот код на дельфи
Используется синтаксис Delphi
procedure S1();
var     b: array[0..100000] of byte;
begin
        b[1] := 1;
end;

begin
        S1();
end.
и результат его компиляции под x86 (только процедура S1) с опциями по умолчанию
Используется синтаксис ASM
.00403A40: 50                             push        eax
.00403A41: B818000000                     mov         eax,000000018
.00403A46: 81C404F0FFFF                   add         esp,0FFFFF004 --1 ;'  Ё♦'
.00403A4C: 50                             push        eax
.00403A4D: 48                             dec         eax
.00403A4E: 75F6                           jnz        .000403A46 --1
.00403A50: 8B842400800100                 mov         eax,[esp][000018000]
.00403A57: 81C460F9FFFF                   add         esp,0FFFFF960 ;'  ∙`'
.00403A5D: C644240101                     mov         b,[esp][1],1
.00403A62: 81C4A4860100                   add         esp,0000186A4 ;' ☺Жд'
.00403A68: C3                             retn ; -^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-
Покажите где здесь проверка переполнения стека? Я вижу только запись в каждую страницу, но никаких проверок не вижу.

-- 01.06.2018, 12:42 --

Или Вы именно запись каждой страницы стека назвали его проверкой? Тогда да, согласен, "проверяется".

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение01.06.2018, 13:16 


27/08/16
10195
Dmitriy40 в сообщении #1316676 писал(а):
Вот код на дельфи

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

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение01.06.2018, 14:58 
Аватара пользователя


07/02/12
1433
Питер
Dmitriy40 в сообщении #1316676 писал(а):
и результат его компиляции под x86 (только процедура S1) с опциями по умолчанию

Посмотрел, как делает MS VS 2012 C++ в x86 - он вызывает функцию chkstk для выделения стека для экзотических функций. Внутри она бежит по страницам. Но ничего не пишет, просто читает по одному DWORD-у из каждой.

В x64 же она пишет по одному нулевому байту в каждую страницу.

Память (и Commit и Working Set) в обоих случаях не растет (точнее растет, но в значительно меньших объемах, чем занимают массивы).

На мой взгляд, оптимальнее было бы просто проверить значение стека на выход за пределы допустимой области, не пробегая по всем страницам. Мне кажется, где-то я такую реализацию даже видел. Вероятно, из встроенных библиотек VS C++ затруднительно получить информацию о том, где граница находится - вот ее и щупают методом тыка, считая, что варианты с выделением огромных малоиспользуемых массивов в локальных переменных несущественны.

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение01.06.2018, 15:36 


27/08/16
10195
bondkim137 в сообщении #1316695 писал(а):
Память (и Commit и Working Set) в обоих случаях не растет (точнее растет, но в значительно меньших объемах, чем занимают массивы).
Интересно, почему?

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение01.06.2018, 17:47 
Аватара пользователя


07/02/12
1433
Питер
Какие-то оптимизации ОС. Вероятно, забитая нулями страница памяти стека не считается использованной в x64.
Разные ОС и даже разные версии одной ОС по-разному себя ведут при работе с виртуальной памятью и файлом подкачки. Я сейчас смотрел на свежей Win10 x64.

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение02.06.2018, 09:54 


08/10/10
50
Dmitriy40 в сообщении #1316488 писал(а):
Вы правы, но осветили лишь одну сторону проблемы
Я не обязан освещать все стороны. Я с самого начала сказал, что речь пойдет только о Windows и только о стеке режима пользователя.
Dmitriy40 в сообщении #1316488 писал(а):
а есть ещё и переполнение физической памяти (вместе с файлом подкачки).
Это мной тоже было упомянуто:
iakovk в сообщении #1316323 писал(а):
Если нету, программа получает исключение с кодом STATUS_STACK_OVERFLOW.
Dmitriy40 в сообщении #1316488 писал(а):
И если пример успешного выделения в стеке более миллиона терабайтов, что намного превышает размер памяти вместе с файлом подкачки (впрочем аналогичное можно проделать и на x86 системе, только описать совокупность условий сложнее), Вас не убеждает, то мне добавить нечего.
Интересно, а в чем вы хотели меня убедить?

-- Сб июн 02, 2018 11:18:25 --

bondkim137 в сообщении #1316695 писал(а):
Посмотрел, как делает MS VS 2012 C++ в x86 - он вызывает функцию chkstk для выделения стека для экзотических функций.

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

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение02.06.2018, 12:45 
Аватара пользователя


07/02/12
1433
Питер
iakovk в сообщении #1316795 писал(а):
По всей видимости это делается только при сборке в отладочной конфигурации
Нет, именно релизной, с включенными оптимизациями

iakovk в сообщении #1316795 писал(а):
Dmitriy40 в [quote="Dmitriy40 в сообщении #1316488 писал(а):
а есть ещё и переполнение физической памяти (вместе с файлом подкачки).
Это мной тоже было упомянуто:
iakovk в сообщении #1316323 писал(а):
Если нету, программа получает исключение с кодом STATUS_STACK_OVERFLOW.
Это две разные вещи. Грубо говоря, в первом случае совсем кончаются страницы памяти у ОС. Во втором - область стека одного из потоков (технически, как мы выяснили для конкретной архитектуры и пока не нашли иных реализаций - происходит обращение к странице адресного пр-ва процесса, специально помеченной для выскакивания этой ошибки).

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение02.06.2018, 18:10 


08/10/10
50
Я был немножко неправ. Исправляюсь.
При создании потока в Win32 создается регион в адресном пространстве процесса под стек этого потока. При этом память не выделяется; резервируется только адресное пространство. Размер региона определяется параметром компоновщика /STACK и прописывается в заголовке исполняемого файла. При отсутствии параметра - 1MB. При исчерпании всего региона возникает исключение STATUS_STACK_OVERFLOW.
Память под стек выделяется по мере надобности. При этом начальное состояние уже содержит некоторое количество памяти - определяется все тем же параметром компоновщика. Следом за этой памятью расположена страница со специальным атрибутом защиты: PAGE_GUARD. При этом, если попытаться получить доступ к этой странице, возникнет исключение STATUS_GUARD_PAGE_VIOLATION.
Таким образом, выделение памяти под стек осуществляется по мере надобности: когда текущая память исчерпана, поток натыкается на спецстраницу, получает исключение STATUS_GUARD_PAGE_VIOLATION и где-то в недрах системы (я не знаю где) выделяется память из резервированного региона (если она есть).
Если же регион целиком исчерпан, то возникает исключение STATUS_STACK_OVERFLOW.
Для иллюстрации некоторых из этих соображений предлагаю программку:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>
#include <windows.h>

int recCount = 0;
#define DATA_SIZE 1024

int ComputeStackSize()
{
        MEMORY_BASIC_INFORMATION mbi;
        int retVal = VirtualQuery(&mbi, &mbi, sizeof mbi);
        return mbi.RegionSize;
}

void RecFunc()
{
        recCount++;
        int data[DATA_SIZE];
        for (size_t i = 0; i < DATA_SIZE; i++)
        {
                data[i] = i;
        }
        int stackSize = ComputeStackSize();
        std::cout << "stackSize = " << stackSize << "\n";
        RecFunc();
        recCount--;
}

void DoTest()
{
        try
        {
                RecFunc();
        }
        catch (const std::exception&e)
        {
                std::cout << "C++ exception: " << e.what() << ", recCount = " << recCount << "\n";
        }
}

int main()
{
        std::cout << "stack overflow test. Calling recursive function\n";
        __try
        {
                DoTest();
        }
        __except (EXCEPTION_EXECUTE_HANDLER)
        {
                auto ec = GetExceptionCode();
                std::cout << "structured exception: " << std::hex << ec << ", recCount = " << std::dec << recCount << "\n";
        }
        return 0;
}
 

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение14.06.2018, 13:07 


06/04/18

323
Итак, я использую MinGW и у меня вот какая странность. Есть код:
Используется синтаксис C++
#include <iostream>
using namespace std;

int main() {
        double block[1000000];
        for (int i=0; i<1000000; i++){
                block[i]=i;     }
        cout << block[999999];
}
Компилируется нормально, после запуска программа (как и ожидалось) вылетает. Чтобы предотвратить вылет, можно использовать g++ main.cpp -o main.exe -Wl,--stack,8388608. То есть повышение размера стека срабатывает без проблем. Но что, если использовать другой код
Используется синтаксис C++
#include <iostream>
using namespace std;

int main() {
        double block[1000];
        for (int i=0; i<1000; i++){
                block[i]=i;
        }
        cout << block[999];
}
и указать другой параметр линкеру: -Wl,--stack,128 ? Программе потребно 8 тыс байт, а выделяется всего 128. А вот что: никаких проблем с запуском не возникает. На выходе я получаю свое число, для которого по задумке не должно было быть места. Видимо есть некий системный минимум, да?
iakovk в сообщении #1316434 писал(а):
Munin в сообщении #1316346 писал(а):
И не было бы никакого ограничения в 1 Мб.
А его и нет.
Как это нет?

(Техническому персоналу)

Фразу -Wl,--stack,128 невозможно выделить курсивом. Проверьте сами.

 Профиль  
                  
 
 Re: Что такое аппаратный стек
Сообщение14.06.2018, 13:58 
Заслуженный участник


27/04/09
28128

(Оффтоп)

А зачем курсивом, когда есть tt.

-Wl,--stack,128

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

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 56 ]  На страницу Пред.  1, 2, 3, 4  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group