2013-12-11 3 views
1

Адрес функции имеет другое значение внутри и снаружи DLL.Значения указателей функций внутри и снаружи DLL

Несколько упрощая, у меня есть следующий код в DLL

typedef struct Holder Holder; /* Struct */ 
    typedef int (*pfn_t)(Holder*); /* Function pointer */ 
    struct Holder { pfn_t pfn; } 

    int IsSame(Holder *h){ return h->pfn == IsSame; } 

В основной программе, у меня есть:

Holder h = { IsSame }; 
    assert(IsSame(&h)); 

в Assert пожаров! Проблема в том, что h.pfn задан адресом таблицы перехода в main.exe, тогда как код в DLL сравнивает это с адресом функции в DLL.

Есть ли какие-либо магические аннотации или варианты ссылок, которые я могу использовать, чтобы убедить утверждение не стрелять?

Обратите внимание, что это находится в Windows. Posix разделяемого библиотеки модель сильно отличается

+1

[Этот вопрос] (http: // stackoverflow .com/questions/19134124/are-two-function-to-the-same-function-always-equal) могут быть связаны, особенно последний абзац принятого ответа. – Tibo

+0

адрес печати каждой функции. на самом деле это не должно срабатывать – qwr

+0

@Tibo: Если вы имеете в виду «Встроенная функция с внешней связью должна иметь один и тот же адрес во всех единицах перевода». - Да, это то, что я хочу быть правдой ... но это не так. Как отмечено в комментарии, DLL - это Undefined Behavior, а компилятор Microsoft не справляется с ними совершенно. –

ответ

2

Вашей проблемой может быть причиной того, что (и не имеет эту проблему.):

вызова функции проходит через дополнительные инструкции JMP .so это относительный адрес

Вместо этого, если вы будете использовать LoadLibrary() GetProcAddress(), он получит адрес функции dll.

+0

Нет. Это не связано с моей проблемой. Я не использую инкрементную привязку. Проблема в том, что функция экспортируется из DLL через .DEF-файл, а именно _that_, который вводит таблицу перехода. –

+0

@MartinBonner Я прокомментировал это в одном из своих комментариев. Но я думаю, что его имя - инкрементное связывание. и я добавил getprocaddress в качестве дополнения, чтобы решить эту проблему – qwr

+0

Ah. По инкрементной привязке я имею в виду возможность связывать изменения с существующим исполняемым файлом. Это довольно отличается от того, как связана DLL (хотя оба они используют дополнительный уровень косвенности). –

0

Если вы хотите выполнить такое сравнение функций, вы должны использовать GetProcAddress или экспортировать интерфейс в своей DLL, который инициализирует любые указатели функций DLL, чтобы убедиться, что адреса, которые вы сравниваете, являются адресом функции, как видно модулю, который он находится вместо батута из .exe в DLL, который является частью магии загрузчика Windows (TM).

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

Смежные вопросы