Последствия нескольких слабых символов (C Linker) - PullRequest
0 голосов
/ 12 ноября 2018

У меня просто вопрос о потенциальной проблеме нескольких слабых символов, этот вопрос из моего учебника:

Один модуль A:

int x;
int y;
p1() {...}

другой модуль B:

double x;
p2() {...}

и мой учебник говорит, что 'запись в x в p2 может перезаписать y' Я могу отчасти понять идею учебника (двойной х - вдвое больше, чем int x, а int y помещается сразу после int x, здесь возникает проблема), но все же теряется в деталях, я знаю, когда есть несколько слабых символов, компоновщик просто случайным образом выберет один, поэтому мой вопрос в том, какой x модуля, который выберет компоновщик, приведет к записи в x в p2 и перезапишет y.

Это мое понимание: если компоновщик выберет int x модуля A , это приведет к последствию, потому что в этом случае x, y являются 4 байтами и p2 (изображение после компиляции есть один код сборки movq по сравнению с movl в p1) изменит 8 байт, поэтому перезаписать y.

Но мой инструктор сказал, что если только компоновщик выберет двойной x модуля B , это приведет к перезаписи y, почему, я прав или мой инструктор прав?

1 Ответ

0 голосов
/ 12 ноября 2018

В соответствии с ISO C программа вызывает неопределенное поведение. Используемое внешнее имя должно иметь в программе ровно одно определение. *

«Слабые символы» - это понятие в некоторых динамических библиотечных системах, таких как ELF в GNU / Linux. Эта терминология здесь не применима. Говорят, что компоновщик, который допускает множественные определения внешнего символа, реализует модель «смягченный ref / def». Этот термин взят из раздела 6.1.2.2 Обоснование ANSI .

Если мы рассматриваем смягченную модель ref / def как документированное расширение языка, то множественные определения имени становятся локально определенным поведением. Тем не менее, что, если они неправильно напечатаны? Это почти наверняка не определено из-за того, что ситуация напоминает псевдоним псевдонимов. Возможно, что если один модуль имеет int x; int y;, а другой - double x, то запись через псевдоним double x приведет к засорению y. На это нельзя положиться. Это очень плохой способ получить эффект псевдонима специально; Вы хотите использовать union между двумя структурами или чем-то подобным.

Теперь о «слабых символах»: это внешние имена в общих библиотеках, которые могут быть переопределены альтернативными определениями. Например, большинство функций в библиотеке GNU C в системе GNU / Linux являются слабыми символами. Например, программа может определить свою собственную функцию read для замены функции POSIX. Сама библиотека не сломается, независимо от того, как переопределено read; когда ему нужно вызвать read, он не использует слабый символ read, но некоторые внутренние псевдонимы, такие как __libc_read. Этот механизм важен; это позволяет библиотеке соответствовать ISO C. В строго соответствующей программе ISO C разрешается использовать read в качестве внешнего имени.


* В стандарте ISO C99 это было дано в 6.9 Внешние определения : "Если идентификатор, объявленный с внешней связью, используется в выражении (отличном от части операнда оператор sizeof, результатом которого является целочисленная константа), где-то во всей программе должно быть ровно одно внешнее определение для идентификатора, в противном случае должно быть не более одного. "

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