Текущая версия FastMM в сравнении с Delphi XE по умолчанию - PullRequest
3 голосов
/ 04 ноября 2011

У нас возникли проблемы с обработкой кода сторонних компонентов в Delphi XE. Я говорю сторонние, потому что наше основное приложение не реализует какой-либо многопоточный код сам по себе. Я определил, что странные повреждения памяти происходят, если я использую SimpleShareMem (у нас есть несколько dll, которые делятся строковыми данными с основным приложением), но эти ошибки исчезают, если я устанавливаю модуль FastMM4. И под странным я подразумеваю, что ошибки редко бывают одинаковыми дважды подряд, хотя они находятся в одной общей области. Первоначально я установил FastMM4, чтобы попытаться определить причину ошибок, но на самом деле они просто не возникают при его установке. Я установил условия в своем наборе опций, которые позволяют мне переворачивать все модули в группе проектов между SimpleShareMem и FastMM и могут довольно легко продемонстрировать мой вывод.

Мой непосредственный пример - TRichView. Я выяснил, что когда у меня включена проверка орфографии hunspell, я могу выдавать ошибку в или рядом с процедурой PaintBuffered / PaintTo, одновременно вставляя и прокручивая клик вверх, довольно много раз (это отличается от того, сколько раз мне нужно сделать это, чтобы произвести ошибку). Иногда это внешнее исключение, которое разрешается в появившемся исключении, в других случаях я достигаю переполнения стека в коде обработки исключений.

Другим примером, с которым я столкнулся, является система удаленного / файлового мониторинга AnyDAC (DA-SOFT), также работающая в отдельном потоке, которая не будет работать с SimpleShareMem, но отлично работает с FastMM4.

Основываясь на этом опыте, я вынужден строить с использованием модуля FastMM4 для производственных сборок, как бы странно это ни казалось мне. Конечно, я всегда сначала подозреваю свой собственный код, поэтому мне интересно, есть ли что-нибудь, что я мог бы сделать, чтобы обострить проблему, хотя FastMM4 не показывает основное приложение как имеющее какие-либо повреждения стека и т. Д.

Итак, мой вопрос: может ли кто-нибудь придумать причину, по которой FastMM4 будет работать лучше для многопоточных операций, чем какая-либо версия FastMM, которую использует Delphi XE?

Обновление: я хотел бы добавить, что я провел некоторое тестирование, используя более старую концепцию Sharemem / borlndmm.dll, и это тоже прекрасно работает.

Обновление 2 : Спасибо за предложения. Я пытался найти heisenbug, который вызывает мою проблему, с очень небольшим успехом. У меня есть дополнительное наблюдение.

Если я изменю основное приложение, чтобы оно не загружало DLL, нужную для ShareMem, у меня не возникнет проблем ни с журналированием AnyDAC, ни с TRichView, независимо от того, какой менеджер памяти я использую. Сам процесс загрузки этой DLL (которая запускает начальный экземпляр FastMM и используется совместно с основным приложением) вызовет проблему, даже если я не делаю вызовов в эту DLL. Следующее, что я собираюсь сделать, - это изменить основное приложение, чтобы включить динамическую загрузку этого dll (и, таким образом, принудительно установить диспетчер памяти в основное приложение) и посмотреть, будет ли это иметь значение.

Обновление 3: Динамическая загрузка dll имеет тот же эффект, что и не загрузка ... все работает.

1 Ответ

5 голосов
/ 04 ноября 2011

Менеджер памяти, встроенный в Delphi XE, является урезанной версией FastMM4.

Сам распределитель блоков памяти идентичен, но механизм совместного использования не одинаков.

По умолчанию в FastMM4Options.inc установлено следующее условие:

{Define this to enable backward compatibility for the memory manager sharing
 mechanism used by Delphi 2006 and 2007, as well as older FastMM versions.}
{$define EnableBackwardCompatibleMMSharing}

Он создаст скрытый дескриптор окна для библиотек для извлечения экземпляра диспетчера общей памяти - так он работал с Delphi 2006 и 2007.

Этот вид совместного доступа больше не существует в урезанной версии FastMM4, реализованной в GetMem.inc, начиная с Delphi 2009 - в которой реализовано только отображение файлов менеджера совместно используемой памяти (что является новым методом). Для одной из библиотек может потребоваться старая версия общего ресурса диспетчера памяти, он не может найти экземпляр диспетчера общей памяти, поэтому использует собственный распределитель памяти и не может обрабатывать общую память (например, string экземпляры).

Это единственное различие, которое я обнаружил между двумя версиями, и это может быть причиной того, что совместное использование не работает должным образом в вашей программе. У вас может быть несколько библиотек, скомпилированных с Delphi 2006 или 2007, и Embarcadero не рекомендовал использовать метод совместного использования (чтобы сохранить несколько байтов кода?).

...