Тип String в Delphi является предметом автоматического освобождения выделенной памяти при выходе переменной из области видимости.
Реализуется это с помощью счетчика ссылок.
Присвоили переменной, передали параметром в функцию - счетчик увеличился.
Присвоили переменной другое значение или вышли из функции - счетчик уменьшился.
Счетчик стал равен 0 - освобождаем выделенную память.
Это является источником проблем при использовании DLL: приложение и DLL являются независимыми исполняемыми файлами, может даже скомпилированными разными компиляторами. Соответственно, в каждом из них код самостоятельно выделяет память и освобождает. Конкретнее - существует менеджер памяти, который отвечает за это.
Когда мы передаём string из главного модуля в функцию DLL мы выделили память под неё в главном модуле.
Но, поскольку DLL сделана на Delphi и работает со string как описано выше, вполне возможна ситуация, когда код DLL попытается освободить память, выделенную под string, которая пришла ему в функцию в качестве параметра.
Но освобождать он будет с помощью своего менеджера памяти, поскольку ничего не знает о каких-либо других.
А менеджер памяти не имеет в своем списке тот блок памяти, в котором находится данная строка.
Вот в этом месте возникает ошибка.
Аналогично если строка создаётся в DLL и возвращается наверх в результатах вызова своей функции.
Решается это подменой менеджера памяти в DLL на тот, что в основном модуле. Я не знаю, предусмотрено ли такое при создании DLL в HiAsm.
В данном случае доступ к символам строки по индексу _data.sdata[1] приводит к копированию строки. Следовательно, предыдущая строка, вероятно, уничтожается, что и приводит к ошибке.
pchar(_data.sdata) конструирует новую строку в своём менеджере, копируя исходную строку, но не уничтожая её. Возможно, так и обходили проблему общего менеджера памяти - создавали копию строки.
И да, на FPC ошибки нет, возможно, потому что там нет копирования строки при _data.sdata[1] (особенности реализации компиляторов).
Поскольку FPC как бы основной компилятор, на нём протестировали и забыли. А на Delphi вылезло.
Ответов: 4655
Рейтинг: 760
|
|||
карма: 26 |
| ||
Голосовали: | tom-it, envoy_sky |
Редактировалось 3 раз(а), последний 2025-02-16 18:35:47