Spread the love

DelphiMVCFramework. Собственный обработчик ошибок

    Осенью я написал на Delphi небольшой REST-сервис для обмена данными с информационной системой другой компании. По регламенту информационного взаимодействия ответ на HTTP-запрос с ошибкой должен

Читать на сайте автора.

NGINX. Фиксим "connect() failed (10061: No connection could be made because the target machine actively refused it) while connecting to upstream"

    Несколько недель тому назад я заметил, что у одного из наших заказчиков NGINX спамит в error.log ошибки начинающиеся с «connect() failed (10061: No connection could

Читать на сайте автора.

Apple Platforms Patch для RAD Studio 10.4.1

    Компания Embarcadero выпустила второе обновление для RAD Studio 10.4.1 Sydney. Оно улучшает поддержку iOS 14, macOS 11 Big Sur (Intel) и XCode 12. Эти операционные

Читать на сайте автора.

Использование переменных среды в FireDAC

    Environment variables (переменные среды или переменные окружения) появились в 7-й версии Unix в 1979 году и с тех пор используются всеми операционными системами для хранения

Читать на сайте автора.

Добавление EurekaLog в программу вызывает Integer Overflow?

К нам обратился человек, который пожаловался на то, что его приложение работало нормально, пока он не добавил в него EurekaLog. После включения в проекте EurekaLog стало появляться исключение Integer Overflow. Исключение происходило внутри функции _UStrCatN (функция конкатенации нескольких строк в RTL).

Функция _UStrCatN написана на ассемблере, но если вникнуть в смысл проверок, то получится что-то такое:

  DestLen := {... вычисляется длина результирующей строки ...};      
if DestLen < 0 then
_IntOver;

где _IntOver — это функция RTL, которая и вызывает исключение Integer Overflow.

Что происходит? Как длина строки может быть отрицательной? Это баг в EurekaLog?

Указанная проверка внутри _UStrCatN должна ограничить строки 2 Гб памяти: если результат сложения всех строк будет больше 2 Гб, то произойдёт переполнение, и длина станет отрицательной. Таким образом, Integer Overflow при сложении строк может возникать, если результат слишком большой.

Но при чём тут тогда EurekaLog? И как проверка может срабатывать, если мы складываем небольшие строки? (клиент подтвердил это логом)

Такое «ложно-положительное» срабатывание возможно, если вы проводите операцию с уже удалённой строкой.

Посмотрите на такой код:

var
Marker: String;

function ReadLine: String;
begin
// ...
Marker := { ... };
// ...
end;

begin
// ...
Data := Data + Marker + ReadLine;
// ...
end;

Видите ли вы проблему в этом коде?

Чтобы понять проблему, нужно знать как выполняется строка «Data := Data + Marker + ReadLine;«. На псевдо-коде это выглядит как-то так:

Param0 := Pointer(Data);
Param1 := Pointer(Marker);
Param2 := Pointer(ReadLine);
_UStrCatN(Data, [Param0, Param1, Param2]);

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

Вот вам и проблема: оператор сохраняет указатель на строку Marker, но строка Marker меняется внутри функции ReadLine. Это означает, что сохранённый указатель будет указывать на старую строку. Таким образом, на вход функции _UStrCatN попадёт уже удалённая строка.

Заметьте, что без EurekaLog в проекте этот баг не является «проблемой». Действительно, удалённая память просто помечается как свободная, но её содержимое не очищается. Это значит, что _UStrCatN успешно проведёт конкатенацию с уже удалённой строкой. И результат операции, скорее всего, будет корректным. Т.е. баг в коде есть, но его совершенно не видно, поскольку программа функционирует полностью правильно.

Ситуация меняется в корне, если в проект добавляется EurekaLog (или любой другой инструмент для отладки проблем с памятью). По умолчанию в EurekaLog включены проверки памяти. Это означает, что удалённая память будет очищена. Как правило, это делается шаблоном вроде DEADBEEF. Заметьте, что Integer представление DEADBEEF — отрицательно (равно -559038737). Т.е. прибавление к этому числу длин нескольких небольших строк также даст отрицательное число.

Иными словами, если в проект добавлена EurekaLog, то операция с уже удалённой строкой больше не будет успешной. Ранее скрытый баг теперь виден.

Читать на сайте автора.

Третий день DelphiCon Worldwide 2020

    Сегодня, 19 ноября, третий день DelphiCon Worldwide 2020 — официальной онлайн-конференции посвященной Embarcadero Delphi.

Читать на сайте автора.

Можно ли сэкономить набирая junior специалистов?

Дисклеймер №1: По стопам предыдущих двух статей «Эффективность по Skunk Works» и «У нас нет ресурсов для ревью кода»

Дисклеймер №2: Безусловно разделение на junior-middle-senior,

Читать на сайте автора.

Второй день DelphiCon Worldwide 2020

    17 ноября началась DelphiCon Worldwide 2020 — официальная онлайн-конференция посвященная Embarcadero Delphi. Для меня важнейшим результатом первого дня конференции была презентация Embarcadero RAD Studio, Delphi

Читать на сайте автора.

Embarcadero Delphi roadmap на 2020/2021

    Марко Канту обнародовал Delphi roadmap на 2020/2021 годы. В этом году больше релизов RAD Studio не будет. Версии RAD Studio 10.4.2 и 10.5 запланированы на

Читать на сайте автора.

DelphiCon Worldwide 2020

Сегодня, 17 ноября, стартует DelphiCon Worldwide 2020. Первые доклады: 18:00. Opening Keynote: The State of Delphi. Marco Cantù (Delphi Product Manager, Embarcadero Technologies).19:00. Delphi at

Читать на сайте автора.