Можно ли вызвать экспортированный частный метод в С++

Можно ли вызвать приватный метод класса, экспортированного из DLL?
Будет ли он скрыт от людей, которые хотели бы его использовать, но не должны?
спасибо :)


person Idov    schedule 18.06.2011    source источник
comment
Я был бы удивлен, если бы компилятор позволил вам пометить частную функцию-член как экспортируемую.   -  person MerickOWA    schedule 18.06.2011
comment
@MerickOWA: C ++ ничего не знает о библиотеках DLL, поэтому на языке можно реализовать функции класса во многих библиотеках DLL (если это не запрещено компилятором). Я думаю, что этого не произойдет, поскольку вы можете распределять функции по единицам кросс-трансляции (obj-файлы), поэтому их распространение по библиотекам DLL является проблемой для компоновщика, который вообще не применяет C++-совокупность, AFAICT (за исключением -mange искаженные имена функций в сообщениях об ошибках).   -  person Macke    schedule 18.06.2011


Ответы (2)


Да, это возможно, но вам нужно использовать грязные приемы приведения типов или полагаться на полунеопределенное поведение, но наверняка вы можете вызвать экспортированную функцию, независимо от ее статуса private/public.

Язык не обеспечивает защиту от злоумышленников. Это поможет всем играть по правилам, но не защитит от тех, кто пытается сломать систему.

Например:

  • используйте GetProcAddress(), чтобы получить адрес функции, привести его к правильному типу функции-члена и вызвать его.
  • создайте модифицированный заголовочный файл класса, объявив все общедоступным (или просто добавьте статическую функцию void crowbar() ), скомпилируйте его. (Неопределенное поведение, поскольку вы нарушаете правило одного определения, но, вероятно, оно сработает...)

Не полагайтесь на закрытое ключевое слово C++ для обеспечения безопасности.

person Macke    schedule 18.06.2011
comment
Для указателя, полученного с помощью GetProcAddress, не существует правильного типа функции-члена. В большинстве случаев фактический вызов потребует написания некоторого ассемблера. Но это возможно. - person Ben Voigt; 18.06.2011
comment
@Ben: я предположил, что вызов невиртуальной функции-члена (если это вообще функция-член) с помощью thiscall довольно прост. Есть ли другие проблемы? (Просто любопытно) - person Macke; 18.06.2011
comment
@Macke: Да, вам нужно каким-то образом передать указатель this, а соглашение о вызовах thiscall не соответствует ни cdecl, ни stdcall, поскольку thiscall передает указатель this в регистр, а не использует стек. Возможно, он совместим с fastcall, не помню. - person Ben Voigt; 18.06.2011
comment
@Ben: я предполагал, что вы можете приводить указатели функций к соглашениям о вызовах. Если нет, то требуется сборка. Как вы говорите, вам нужно thiscall, но это должно быть неявно в типе ptr-to-member-function. - person Macke; 18.06.2011
comment
@Macke: функция «указатель на член» поддерживает поиск в vtable, виртуальные базовые классы, требующие настройки указателя this, и т. д. Функция «указатель на член» не является указателем на функцию. GetProcAddress возвращает указатель на функцию, а не указатель на член. Результат GetProcAddress должен быть приведен к правильному типу указателя функции (включая соглашение о вызовах), но я не думаю, что правильный тип не может быть написан на C++. - person Ben Voigt; 18.06.2011
comment
Обратите внимание, что виртуальная поддержка должна существовать независимо от того, является ли целевая функция-член виртуальной или нет, поскольку они не являются частью типа pmf. Код, вызывающий pmf, не может узнать, был ли pmf создан из виртуальной или невиртуальной функции. - person Ben Voigt; 18.06.2011
comment
@Бен: Верно. Я знал о необходимости этого, но, так сказать, не соединил точки должным образом. Было бы интересно посмотреть, что нужно, чтобы заставить его работать. :) - person Macke; 18.06.2011

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

Строго говоря, любая функция, для которой компилятор генерирует внешний экземпляр, может быть вызвана любым собственным кодом. Экспорт с помощью DLL значительно упрощает поиск адреса кода функции.

person Ben Voigt    schedule 18.06.2011