Исключения страницы Guard в Delphi?

len(di) равно 4. Таким образом, цикл

for i in range(len(di)):

будет повторяться 4 раза. Поскольку range работает (от нижней границы, которая по умолчанию равна 0, если она не указана, до 1 под верхней границей), i будет 0 в первом повторении, 1 во втором повторении , и так далее. Чтобы вычислить, сколько объектов range(x, y) генерирует, в этом случае, как часто for i in range(x, y) будет повторяться, вы можете просто сделать number of repetitions = y - x. Так что в этом случае: len(di) - 0 (default lower bound) = 4.

Цикл

for j in range(i+1, len(di)):
    print(i)

будет повторять команду print(i) len(di) - (i + 1) раз. Имейте в виду, i определяется внешней петлей. Итак, во время первого цикла

for i in range(len(di)):

i равно 0, поэтому команда print(i) будет выполнена 4 - (0+1) = 3 раз - она ​​напечатает i(=0) 3 раза. Во втором цикле i равен 1, поэтому он будет напечатан 2 раза и так далее. Итак, вот что происходит, отформатировано как код для лучшей читаемости:

First outer loop: 
i = 0
total = di[i] = di[0] = 96
--> first inner loop of first outer loop:
    j = i + 1 = 1
    i is printed -> prints 0

    second inner loop of first outer loop:
    j = j+1 = 2
    i is printed -> prints 0 again

    third inner loop of first outer loop:
    j = j+1 = 3 --> since len(di) = 4, the upper bound of range(i+1, len(di)) is reached, so this is the last Repetition
    i is printed -> prints 0 again

Second outer loop:
i = 1
total = di[1] = 15
--> first inner loop of second outer loop:
    j = i+1 = 2
    i is printed -> prints 1

    second inner loop of second outer loop:
    j = i+1 = 3  -> upper bound of range reached, last repetition
    i is printed -> prints 1 again

Third outer loop:
i = 2
total = di[2] = 33
--> first inner loop of third outer loop:
    j = i+1 = 3  -> upper bound of range is reached, only Repetition
    i is printed -> prints 2

Fourth (and final) outer loop:
i = 3 -> upper bound of range(len(di)) reached, last Repetition
total = di[3] = 87
since j = i+1 = 4, the inner loop does not get executed at all (both bounds of range are equal), so 3 doesn't get printed

end of code.
6
задан mghie 19 April 2009 в 10:32
поделиться

2 ответа

Структурированная обработка исключений Windows (SEH) имеет двухфазную структуру. Когда возникает исключение, Windows сначала ищет обработчик исключения, следуя зарегистрированной цепочке обработчиков исключений (заголовок которой хранится в fs: [0] на x86, то есть первое двойное слово в сегменте, на который указывает сегмент FS. register - вся эта уродливая 16-битная логика смещения сегментов не исчезла в 32-битном, она просто стала менее актуальной).

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

Эти функции обычно проверяют тип исключения и возвращают код, указывающий, что делать. Один из кодов, которые могут быть возвращены, - это, по сути, «игнорировать это исключение и продолжить».Если Windows это увидит, она сбросит указатель инструкции на точку исключения и возобновит выполнение. Другой код указывает, что этот кадр исключения должен обрабатывать данное исключение. Третий код: «Я не собираюсь ловить это исключение, продолжайте поиск». Windows продолжает вызывать эти функции фильтра исключений, пока не найдет тот, который так или иначе обрабатывает исключение.

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

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

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

Вы можете прочитать больше о SEH в отличной статье Мэтта Питрека в MSJ, написанной более десяти лет назад .

14
ответ дан 8 December 2019 в 14:47
поделиться

From looking at the comments, it looks to me like the "guard page exception" mess takes place entirely within the kernel, and is not something that you need to be worrying about from user space.

You've gotta remember that this article was written for C++, which is nowhere near as advanced as Delphi on the memory management front. The uninitialized pointers issue is a lot less of a mess in Delphi than in C/C++ for two reasons:

  1. Delphi checks for uninitialized variables at compile time, which (for whatever reason) a lot of C compilers tend to have trouble with.
  2. Delphi initializes all of its dynamic memory to 0, so you don't have random heap garbage to deal with that might look like a good pointer when it's really not. This means that most bad pointers give you access violations, which are easy to debug, instead of silently failing and corrupting memory.
2
ответ дан 8 December 2019 в 14:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: