Распределение памяти в Static vs Dynamic Linking C Runtime - PullRequest
2 голосов
/ 17 ноября 2011

Архитектура моей программы включает плагины (dll) и исполняемый файл (очевидно).Мы единственный поставщик плагинов.Мне сказали, что выделение памяти в плагине, а затем освобождение его в исполняемом коде было потенциальной проблемой, если мы статически связывали среду выполнения c.Однако, если мы динамически связали его, была только одна куча, и среда выполнения c имела доступ ко всему этому.Мы переключились на динамическое связывание на основе этого совета, но все, что мы видели с коммутатора, - это головные боли и проблемы, связанные с распределением и установкой новых сред выполнения.(Не знаю, чего мы избежали с точки зрения проблем с выделением памяти.)

Каковы последствия выделения памяти?Скажем, плагин распределяет память, а exe освобождает ее.Есть ли другое поведение между статической и динамически связанной c средой выполнения?Будут ли у нас проблемы со статическим связыванием среды выполнения c, если мы будем использовать плагины?Если мы вернемся к статическому соединению, это испортит обнаружение утечки памяти и отчеты о сбоях?

Соответствует ли некоторые вопросы, поднятые комментариями к Какую версию VC ++ я выбираю - статическую или динамическую? конкретно Какую версию VC ++ я выбираю - статическую или динамическую?

Также есть обсуждение на http://msdn.microsoft.com/en-us/library/abx4dbyh(v=VS.100).aspx.

Ответы [ 3 ]

1 голос
/ 17 ноября 2011

Если вы хотите выделить из кучи в одном модуле и освободить в другом, тогда вам просто нужно динамически связать среду выполнения. Более того, все стороны должны динамически связывать то же самое время выполнения. Как только вы это сделаете, проблем не будет.

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

Что касается того, почему вы все еще страдаете от ошибок во время выполнения, сказать сложно. Я предполагаю, что не все модули ссылаются на одну и ту же версию среды выполнения.


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

0 голосов
/ 17 ноября 2011

Функции для выделения / освобождения памяти сопряжены; вы не можете вызвать my_malloc () и затем использовать free (), или вызвать «новый» оператор C ++, а затем вызвать FreeMem () из некоторой случайной библиотеки:)

Вашему плагину нужен хорошо известный способ выделения и освобождения памяти. Если это делает malloc (), то ваша основная программа, вероятно, может просто сделать free (). Но если он делает что-то более экзотическое (в Windows доступно множество распределителей памяти), API вашего плагина должен предоставить способ, чтобы основной exe-файл мог вызвать плагин для освобождения его данных.

Так что, если ваша основная программа вызывает

foo = plugin->allocate_something()

тогда было бы разумно, чтобы ваш плагин API имел соответствующий

plugin->free_something (foo)

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

0 голосов
/ 17 ноября 2011

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

В общем случае может быть лучше, чтобы плагин отвечал как за выделение, так и за удаление всей памяти.использует.Это подразумевает, возможно, добавление API к плагину для удаления объектов, которые он ранее создал и передал обратно в основное приложение.Это также обеспечивает хорошую изоляцию между плагином и приложением, позволяя плагину использовать специализированные распределители для производительности или по другим причинам.Это то, что делает COM, например.

...