Объем памяти общих библиотек

Имеется ли в общей библиотеке С++ собственное пространство памяти? Или он разделяет процесс вызова? Один?

У меня есть общая библиотека, которая содержит некоторые классы и функции оболочки. Одна из этих функций-оболочек выглядит следующим образом:

libXXX_construct(), который инициализирует объект и возвращает указатель на указанный объект.

Как только я использую libXXX_construct() в программе-вызывателе, где размещен объект? Является ли это в пространстве памяти "вызывающего" или находится в памяти библиотеки?

Ответ 1

Связанный экземпляр общей библиотеки совместно использует пространство памяти экземпляра исполняемого файла, связанного с ним, прямо или косвенно. Это справедливо как для Windows, так и для UN * X-подобных операционных систем. Обратите внимание, что это означает, что статические переменные в общих библиотеках не являются способом межпроцессного общения (что-то, что многие думают).

Ответ 2

Все разделяемые библиотеки совместно используют пространство виртуальной памяти своего процесса. (Включая основной исполняемый файл)

Ответ 3

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

Однако в Windows можно создавать общие переменные, которые позволяют осуществлять межпроцессное общение. Вы делаете это, помещая их в нужный сегмент. По умолчанию Windows использует два типа сегментов: сегменты данных считываются/записываются не разделены, тогда как сегменты кода доступны только для чтения и совместно используются. Однако атрибуты чтения и записи ортогональны. Общий сегмент чтения и записи в библиотеке может использоваться для хранения общих переменных, и он выживет до тех пор, пока не завершится последний процесс.

Будьте осторожны с С++, так как это будет успешно запускать конструкторы и деструкторы при запуске и выходе процесса, даже если вы ставите переменные в разделяемые сегменты.

Подробнее см. в Peering Inside PE: обзор файла для исполняемого файла Win32 Part 2 от Matt Pietrek.

Ответ 4

Ваш объект существует в пространстве памяти вызывающего абонента (на самом деле одно пространство памяти, разделяемое между библиотекой и основным исполняемым файлом)

Ответ 5

Пространство адресов общего доступа, чтобы вы могли обмениваться указателями, однако они не разделяют распределитель (по крайней мере, не на окнах).

Это означает, что если вы вызываете new для выделения объекта внутри общей библиотеки, вы должны вызывать удаление внутри одной библиотеки или могут произойти странные вещи.

Ответ 6

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

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

Ответ 7

Верно, что библиотека будет использовать память в каждом процессе, который загружает ее. Однако, по крайней мере, в Windows, когда несколько процессов загружают одну и ту же DLL, немодифицированные страницы (включая все кодовые страницы) спокойно распространяются под обложками. Кроме того, они не занимают места в файле подкачки, поскольку они поддерживаются исходным файлом.

Я считаю, что это сложнее для .NET из-за компиляции JIT, но все равно будет справедливо для сборок NGENed.

изменить

Это деталь виртуальной машины. Однако вы также можете flag сегмент в DLL для совместного использования через процессы.