Строковое литеральное хранилище C между несколькими копиями процесса или библиотеки

Каково поведение различных систем, когда у вас запущено несколько копий конкретной программы или библиотеки, хранятся ли строковые литералы один раз в ОЗУ или один раз для каждой копии процесса / библиотеки? Что делать, если они хранятся в массиве вроде:

static const char *const foo[] = { "bar", "baz", "buz" };

Ли static изменить поведение памяти для хранения вообще?

Изменить: Поскольку это, вероятно, зависит от платформы, каково поведение компилятора Microsoft в Windows или GCC в Linux (x86)?

5 ответов

Решение

Предполагая, что вы спрашиваете о динамически связанных данных библиотеки, обычно каждый процесс получает свою копию данных, по крайней мере, виртуально. Однако операционная система может использовать ту же оперативную память для хранения этих данных. Если бы данные были затем записаны одним из процессов, то ОС создаст новую копию данных, которую этот процесс может изменить, и позволит другим процессам продолжать смотреть на старую копию. Это известно как Копирование при записи (COW).

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

Некоторые операционные системы, вероятно, не поддерживают COW.

редактировать

Прочитав комментарий к другому посту, я решил вникнуть немного больше.

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

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

Я предполагаю, что это зависит от платформы, так как в языке нет таких спецификаций.

Изменил ли статический режим поведение памяти вообще?

Да, но не в отношении строкового литерала между несколькими копиями процесса или библиотеки.

Поскольку память процессов изолирована (ну, в основном), у каждого процесса есть копия всех строк в его виртуальной памяти. Однако это зависит от компилятора (я не исследовал, как компиляторы обрабатывают различные объявления строковых констант). В общем, если блок данных (или код) отображается в адресном пространстве, он не "загружается" в физическую память больше, чем необходимо. Одна копия хранится в блоке физической памяти (странице), и эта страница отображается на разные виртуальные адреса нескольких процессов. Если вы изменяете данные в виртуальном пространстве одного процесса, создается копия этой страницы, которая сопоставляется со старым виртуальным адресом.

В вашей задаче имеет смысл сохранить все ресурсы как ресурсы PE и загрузить их в коде в файл с отображением в памяти. Каждый экземпляр приложения будет делать это, если это не было сделано предыдущим экземпляром приложения. Таким образом, у вас всегда есть только одна копия констант в памяти.

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

Windows и я полагаю, что Unix/Linux позволяет это, и в первые дни, когда ОЗУ было ограничено, поощряло его использование. Однако это был компромисс между сохранением памяти и защитой памяти. Поскольку диапазон адресов памяти увеличился, а оперативная память стала дешевой, было решено, что это не стоит того. (В Win16 я считаю, что это было по умолчанию; под Win32 для его использования требуется выполнить некоторые шаги вручную)

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

ОБНОВЛЕНИЕ: В Windows у вас может быть только ресурсная DLL, которая может быть помечена как "общая". Это, вероятно, лучший способ справиться с тем, что вы хотите.

Другие вопросы по тегам