![]() |
Модераторы: bsa |
![]() ![]() ![]() |
|
bsa |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
В двух словах: Обычная функция записывается в 2 места объектного файла - область кода и "экспортную" таблицу символов. В области кода находится собственно "почти" машинный код (только вместо адресов вызываемых процедур и глобальных переменных, там ссылки на них или просто мусор - реальные значения подставляются на этапе компоновки), а в области таблицы символов находится запись: <сигнатура функции (считай, ее название и список параметров)> <смещение отностительно области кода> <размер кода> Когда все объектные файлы созданы из исходников, происходит их компоновка линкером. Он читает таблицу импортируемых символов (для простоты, в нее записываются все переменные и функции, которые реализованы в другом объектном файле, каждая запись ссылается на "мусор" в машинном коде), затем ищет требуемый символ (сигнатуру функции/переменной) в экспортных таблицах всех объектных файлов. Если находит, то помещает функцию в результирующий файл (т.е. уже в экзешник) и продолжает до тех пор, пока все символы не будут разрешены. Есть ключевое слово static, которое говорит компилятору, что данный объект не надо включать в экспортную таблицу. Таким образом, в программе может быть миллион одинаковых статических переменных или функциий, которые находятся в разных объектных файлах, и линкер не ругнется - он просто не будет знать о их существовании. Если ты помечаешь функцию словом inline, то (в С++) говоришь компилятору, что данная функция является встраиваемой, поэтому не надо помещать ее в экспортную таблицу (т.е. фактически функция статическая). Таким образом, даже если функцию не удалось компилятору встроить, линкер все равно о ней ничего не узнает. В языке си, будет ругаться, поэтому там надо помечать ее еще и static. P.S.: я попытался использовать простейшую терминологию. Если есть желании знать все в научной, то тебе тут объяснят. |
||||
|
|||||
UnrealMan |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 5 Всего: 32 |
Lampa24, тебе чья лапша больше нравится: vinter-a или mes-а & bsa? ![]() |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
Т.е. я был не прав, говоря, что она является фактически static. |
|||
|
||||
vinter |
|
||||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
причем тут макрося сказал, что она подобна. И что она встраивается на этапе компиляции, что непонятно? именно из-за этого.
линкер к inline функции не имеет никакого отношения, потомучто если inline пожелание было исполнено, то никакой функции нет.
bsa, а ты проверь ;) UnrealMan, хорошь стебаться, есть, что сказать - говори ![]() |
||||
|
|||||
UnrealMan |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 5 Всего: 32 |
Проблема исчезает из-за того, что исчезает нарушение правила одного определения, а задумано оно так для того, чтобы одни и те же inline-функции сразу в нескольких единицах трансляции могли встраиваться во время компиляции (не дожидаясь компоновки). |
|||
|
||||
vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
||||
|
||||
UnrealMan |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 5 Всего: 32 |
||||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 15 Всего: 101 |
компилятор ведет себя в соответствии со стандартом: inline функция имеет один адрес во всех единицах трансляции. технически это означает, что если где-то используется адрес функции, то компилятор генерирует (единственное) определение этой функции. что, заметьте, не мешает ему при вызове этой функции подставлять её встроенное представление вместо вызова, если компилятор считает это нужным. вот как, например, может поступить компилятор:
|
|||
|
||||
vinter |
|
||||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
стандарт другое говорит
так насколько я понял: при inline будет всегда генерироваться новое определение ф-ии, в каждой еденицы трансляции(типо internal linkage чтоли?). Я правильно это понимаю или нет? Следущий вопрос: я сталкивался с ситуацией когда была средних размеров inline ф-ия которая находилась в ашнике, все работало замечательно. Но после добавления нескольких строк появилась ошибка линкера, я вв свое время решил, что это из-за того, что ф-ия перестала встраиватся и из-за этого ошибка. Как это объяснить? gcc 4.0.1 кажется.. |
||||
|
|||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 15 Всего: 101 |
не, vinter, стандарт говорит именно это. и не надо его домысливать, там четко все.
Добавлено через 5 минут и 10 секунд для начала таки переведи приведенную тобой фразу. и читай 7.1
|
|||
|
||||
vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
baldina, ну и что? покад\жи мне в каком месте изначальнеого кода есть
и это не отменяет вопросов заданнных ранее, я ничего не домысливаю, я всего лишь пытаюсь понять. Анрыл вон знает и молчит как партизан, обиделся наверно ![]() |
|||
|
||||
baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 15 Всего: 101 |
в изначальном коде функция определена в ашнике, включаемом в двух файлах. т.е. имеем определение ее в нескольких единицах трансляции.
покуда она не inline это нарушает правило одного определения. как только она становится inline ничего не нарушается. и ошибок компиляции нет. встраивается она или нет совершенно неважно, это деталь реализации. вариант реализации (MSVC так делает) я показал - может иметь место встраивание и не-встраивание одновременно. но это уже не относится к вопросу ![]() Добавлено через 1 минуту и 20 секунд
читай стандарт, тоже знать будешь. думаешь он молчит - время экономит? хочет что бы ты сам прочел. так полезнее. |
|||
|
||||
vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
baldina, остается неотвеченный вопрос
остальное я понял, но не совсем понял смысл этого и еще, встроить функцию это не просто впихнуть ее код где надо, это определенный гемморой. Как тогда быть с единственнно определенной функцией, и как быть с цитаатой из стандарта приведенной мной выше. я прочел, вопросы остались. То, что полезнее не спорю, если бы не Анрыл, я бы стандарт наверно не скоро открыл ![]() |
|||
|
||||
baldina |
|
||||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 15 Всего: 101 |
какая ошибка линкера? в скольких единицах трансляции была эта функция? в скольких разных местах на диске был одноименный ашник с одноименной функцией? хорошо бы код глянуть
Скомпилить код таким образом, что бы функция была определена один раз (по единственному адресу) - это задача компилятора. Определить inline функцию в каждой единице трансляции, где она используется - обязанность программиста. Здесь нет противоречий. Это буквально то, что в стандарте. В чем вопрос? Добавлено через 4 минуты и 19 секунд vinter, стандарт содержит как требования к коду, так и гарантии программисту (требования к компилятору).
Это обязан обеспечить программист
Это обязан обеспечить компилятор |
||||||||
|
|||||||||
vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 8 Всего: 56 |
||||
|
||||
![]() ![]() ![]() |
Правила форума "C/C++: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |