Как правила выбора библиотеки отличаются между золотом и стандартным (bfd) компоновщиком?

Ну, я тоже долго об этом задумывался, и я попытался провести несколько тестов, чтобы лучше понять, что происходит под капотом. Стандартный ответ заключается в том, что после вызова delete вы не должны ожидать ничего хорошего от доступа к этому месту памяти. Однако этого мне не показалось. Что на самом деле происходит при вызове delete (ptr) ? Вот что я нашел. Я использую g ++ на Ubuntu 16.04, так что это может сыграть роль в результатах.

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

Память, выпущенная с помощью delete , по-прежнему кажется выделенной программе, в которую она сначала выделила ее с помощью новый . Я пробовал, и уменьшение использования памяти после вызова delete . У меня было программное обеспечение, которое вырезало около 30 МБ списков через новые вызовы , а затем выпустило их с последующими вызовами delete . Случилось так, что, глядя на монитор системы во время работы программы, даже длительный сон после вызова delete , потребление памяти моей программы было одинаковым. Никакого снижения! Это означает, что delete не освобождает память системы.

На самом деле, похоже, что память, выделенная программой, является его вечно! Тем не менее, дело в том, что при освобождении памяти память может снова использоваться одной программой без необходимости выделять ее. Я попытался выделить 15 МБ, освободив их, а затем выделив еще 15 МБ данных, а программа никогда не использовала 30 МБ. Системный монитор всегда показывал его около 15 МБ. То, что я делал по отношению к предыдущему тесту, заключалось в том, чтобы изменить порядок, в котором все произошло: половина распределения, половина освобождения, другая половина распределения.

Итак, память, используемая программой, может увеличиваться, но никогда не сжиматься. Я думал, что, возможно, память действительно будет выпущена для других процессов в критических ситуациях, например, когда больше нет памяти. В конце концов, какой смысл это сделать, чтобы программа сохраняла свою собственную память навсегда, когда другие процессы просят об этом? Поэтому я снова выделил 30 МБ, и, освободив их, я запустил memtester с такой физической памятью, сколько мог. Я ожидал увидеть, что мое программное обеспечение передает свою память memtester. Но догадаться, этого не произошло!

Я составил короткий скринкаст, который показывает, что в действии:

Чтобы быть на 100% честным, возникла ситуация, когда произошло что-то . Когда я попробовал memtester с большей доступной физической памятью в середине процесса освобождения моей программы, память, используемая моей программой, упала примерно до 3 МБ. Процесс memtester был убит автоматически, хотя и что произошло еще более удивительно! Использование памяти моей программы увеличилось с каждым вызовом на удаление! Это было похоже на то, что Ubuntu восстанавливает всю память после инцидента с memtester.

Взято из http://www.thecrowned.org/c-delete-operator-really- frees-memory

0
задан Dan Stahlke 13 July 2018 в 21:33
поделиться

1 ответ

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

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

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

Архивные библиотеки без индекса символа в наши дни обычно не поддерживаются. Раньше считалось, что линкеры совершают один проход через библиотеку, добавляя член архива, если он удовлетворяет неразрешенную ссылку. Это потребовало, чтобы библиотеки были топологически отсортированы (и для многих систем Unix по-прежнему есть инструмент «lorder»).

Для разделяемых библиотек под действием опции --as-needed мы рассматриваем библиотеку как «нужен», если он удовлетворяет несладкой ссылке из обычного файла объекта. Золото отмечает, что общая библиотека «нужна», даже если ссылка исходит от объекта, который следует за ним в порядке ссылки; Я думаю, что BFD ld отмечает, что он «нужен», только если ссылка предшествует общей библиотеке.

Если вы пытаетесь выяснить, почему линкер считает, что конкретная библиотека - необходимо "или нет, вы можете найти полезный вариант компоновщика -y symbol.

1
ответ дан Cary Coutant 17 August 2018 в 12:07
поделиться
  • 1
    Благодарю. Это очень полезно и дает мне возможность продолжить. Мне жаль, что наш проект не был настолько чувствителен к этим вещам, но это реальность, которая ползет при смешивании десятков библиотек в большой базе кода. – Dan Stahlke 16 July 2018 в 18:15
Другие вопросы по тегам:

Похожие вопросы: