Что должен делать плагин при получении Out of memory?
Select messages from
# through # FAQ
[/[Print]\]

Total Commander -> Написание плагинов для Total Commander

#1: Что должен делать плагин при получении Out of memory? Author: remittorLocation: Russia PostPosted: Fri Nov 15, 2019 18:58
    —
Ни в одном плагине для TotalCmd я не нашёл обработку ошибки Out of Memory.

Сейчас пишу wcx-плагин, в котором все места с выделением дин. памяти имеют проверки. И в случае возникновения оной ошибки управление через ret дойдёт до TotalCmd.

Но честно говоря, в этой ситуации просто хочется вызвать RaiseException и забыть.

Так может так и стоит делать?
В этом случае TotalCmd завершит работу с ошибкой.

#2:  Author: CaptainFlintLocation: Москва PostPosted: Sat Nov 16, 2019 03:08
    —
Сознательно грохать Тотал при возникновении проблемы в плагине — это, конечно, сильно. Лично я бы такой плагин первым делом снёс.

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

#3:  Author: remittorLocation: Russia PostPosted: Sat Nov 16, 2019 12:43
    —
CaptainFlint wrote:
Сознательно грохать Тотал при возникновении проблемы в плагине — это, конечно, сильно.

Во всех плагинах, что я видел, не перехватывается исключение EOutOfMemory/bad_alloc, что ведёт к завершению работы процесса с выдачей ошибки.
Да там вообще нет никакой обработки исключений.
Если в плагине юзается System.String/std::string , то без обработки исключений есть шанс словить EOutOfMemory от плагина.

CaptainFlint wrote:
Лично я бы такой плагин первым делом снёс.

В плагинах DEB И RPM используется System.String и при этом вообще нет отлова исключений. Поэтому можно смело сносить эти плагины, т.к. они могут сгенерить исключение EOutOfMemory.
К тому же в плагине DEB нет проверки результата GetMem, что тоже может привести к "падению" TotalCmd.

В плагине Office2007wlx используется оператор new() , но перехвата исключения bad_alloc нету. Вообще нету try/catch!!!

В плагине NTLinks проверяется результат malloc. А вот результат realloc (вызывается внутри какого то объекта) не проверяется совсем никак.

CaptainFlint wrote:
В API не зря предусмотрены различные коды ошибок в качестве возвращаемых значений. Если возникает нештатная ситуация, считается, что разработчик плагина должен её обработать в своём коде и вернуть ошибку Тоталу, чтобы тот понял, что операция не удалась.

Всегда так и делаю. Вопрос был о другом. Сейчас сам TotalCmd никак не обрабатывает EOutOfMemory/bad_alloc. Поэтому при реальной нехватке памяти вы управление возвратите в TotalCmd, но он сам при этом "свалится" при первой работе с System.String и т.п.

Поэтому и встаёт вопрос: а нафига заморачиваться с ловлей EOutOfMemory/bad_alloc (для крошечных блоков памяти), коли сам TotalCmd не ловит эти исключения?

#4:  Author: CaptainFlintLocation: Москва PostPosted: Sat Nov 16, 2019 14:23
    —
Ну, доступные ресурсы — это такая вещь… Сейчас он свалился от нехватки памяти, а следующий запрос на выделение пройдёт успешно из-за того, что какая-то жирная программа освободила блок или вовсе завершила работу. Кроме того, крошечные блоки могут превратиться в некрошечные, если их размер зависит от внешних факторов. Например, пользователь сдуру открыл десятигигабайтный файл, плагин начал его читать в память (крошечными блоками), исчерпал объём, получил исключение и свалился. Грохать весь Тотал в такой ситуации неразумно, ибо ресурсов в системе для нормальной работы вполне достаточно (если, конечно, плагин освободит всю эту сожранную им память).

#5:  Author: remittorLocation: Russia PostPosted: Sat Nov 16, 2019 15:31
    —
CaptainFlint wrote:
Ну, доступные ресурсы — это такая вещь… Сейчас он свалился от нехватки памяти, а следующий запрос на выделение пройдёт успешно из-за того, что какая-то жирная программа освободила блок или вовсе завершила работу.

Всё верно. Для этого все и должны использовать RAII + try/catch.
Но в описанной вами ситуации сам TotalCmd может в классе System.String или GetMem сгенерировать EOutOfMemory.
Получается, что TotalCmd можно болт забивать на ловлю исключений, а нам нельзя?

CaptainFlint wrote:
Кроме того, крошечные блоки могут превратиться в некрошечные, если их размер зависит от внешних факторов. Например, пользователь сдуру открыл десятигигабайтный файл, плагин начал его читать в память (крошечными блоками), исчерпал объём, получил исключение и свалился.

Зачем весь десятигигабайтный файл читать целиком в память?

CaptainFlint wrote:
Грохать весь Тотал в такой ситуации неразумно, ибо ресурсов в системе для нормальной работы вполне достаточно.

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

Что должен делать плагин, когда в конструкторе какого либо класса произошёл EOutOfMemory при инициализации динамической строки System.String/std::string ?
Из конструктора код ошибки не возвратить. Нужно обрамлять в try/catch весь код.

#6:  Author: CaptainFlintLocation: Москва PostPosted: Sun Nov 17, 2019 15:52
    —
remittor wrote:
Получается, что TotalCmd можно болт забивать на ловлю исключений, а нам нельзя?

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

remittor wrote:
Зачем весь десятигигабайтный файл читать целиком в память?

Да мало ли ситуаций… Скажем, плагин просмотра картинок, который не ожидал, что его вызовут на гигапиксельную Hubble eXtreme Deep Field. Или просмотр кода с подсветкой синтаксиса, где некоторые грамматики требуют полного парсинга. Ну или бывает, что сам файл держать в памяти необязательно, можно обрабатывать потоковым алгоритмом, но результаты парсинга в итоге занимают столько же, а то и больше места (как какой-нибудь JSON, XML).

remittor wrote:
Что должен делать плагин, когда в конструкторе какого либо класса произошёл EOutOfMemory при инициализации динамической строки System.String/std::string ?
Из конструктора код ошибки не возвратить. Нужно обрамлять в try/catch весь код.

Учитывая, что API не является объектно-ориентированным, на верхнем уровне всё равно будет реализация какого-нибудь ListLoad(). Я не вижу, в чём проблема обернуть содержимое этого метода в один большой try/catch. Сложнее, конечно, разобраться с освобождением ресурсов, если исключение всё же произошло, но тут уже от конкретного кода всё зависит.



Total Commander -> Написание плагинов для Total Commander


output generated using printer-friendly topic mod. All times are GMT + 4 Hours

Page 1 of 1

Powered by phpBB © 2001, 2005 phpBB Group