Что произойдет в случае некорректного использования директивы dllimport?


Перевод с блога The Old New Thing. Оригинал здесь.

Теперь мы знаем, что означает директива dllimport, но что если она используется неправильно?

Если вы забудете объявить функцию при помощи dllimport, тогда вы фактически заставляете компилятор вести себя наивным способом, когда он не понимает, что такое dllimport. Когда компоновщик будет определять внешние ссылки для функции, он использует заглушку из библиотеки импорта и все будет работать так как и прежде. Вы лишитесь оптимизации, которую дает dllimport, но код будет работать. Вы просто будете работать в "наивном" режиме.

(До сих пор существует несколько заголовочных файлов в Platform SDK, которые игнорируют использование dllimport. В результате, любой кто использует эти заголовочные файлы для импорта функций из соответствующих DLL будет работать в "наивном режиме". Будем надеяться, что люди, ответственные за эти файлы, узнают себя и исправят проблему в следующей версии Platform SDK.)

Теперь, как насчет обратной проблемы? Что если вы объявили функцию как dllimport, когда она таковой не является. Компоновщик обнаружит это, поскольку он увидит попытку импортировать __imp__FunctionName символ и не сможет его найти, в то время как он найдет обычный FunctionName символ. Когда такое случается, компоновщик выдает сообщение LNK4217. Он исправляет такую ошибку простым созданием фальшивой записи __imp__FunctionName и  инициализацией ее адресом функции FunctionName. В результате, вы импортируете функцию из своего же модуля. Ваш код теперь пройдет через все процедуры, связанные с вызовом импортируемой функции, в которых нет необходимости, в то время как он мог вызвать FunctionName напрямую.

(Бывают случаи, когда компоновщик может вести себя более умно. Например, если он видит вызов call [__imp__FunctionName], он может изменить его на call FunctionName; nop. Команда nop необходима потому что call [__imp__FunctionName] имеет длину 6 байт, а call FunctionName – только пять. Лишний nop восстанавливает синхронизацию.)

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

(Все это касается архитектуры х86. Другие архитектуры могут иметь свои особенности.)

В следующий раз, я расскажу еще немного о библиотеках импорта и раскрою небольшой обман.

Реклама
Запись опубликована в рубрике DLL. Добавьте в закладки постоянную ссылку.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s