Строковое литеральное хранилище C между несколькими копиями процесса или библиотеки - PullRequest
0 голосов
/ 17 сентября 2010

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

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

Изменяет ли static поведение памяти вообще?

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

Ответы [ 5 ]

2 голосов
/ 18 сентября 2010

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

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

Некоторые ОС, вероятно, не поддерживают COW.

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

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

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

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

1 голос
/ 17 сентября 2010

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

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

1 голос
/ 17 сентября 2010

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

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

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

0 голосов
/ 17 сентября 2010

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

0 голосов
/ 17 сентября 2010

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

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

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

...