Как адресовать предупреждение C4191 вокруг вызовов GetProcAddress с помощью FARPROC? - PullRequest
9 голосов
/ 16 ноября 2010

Недавно я попытался использовать параметр / Wall Visual C ++ , чтобы включить все предупреждения, и обнаружил, что следующий код:

typedef BOOL ( WINAPI * TIsWow64ProcessFunction )( HANDLE, BOOL* );
TIsWow64ProcessFunction isWow64ProcessFunction = reinterpret_cast<TIsWow64ProcessFunction> (
    ::GetProcAddress( kernel32DllHandle, "IsWow64Process" ) );

порожден C4191 :

warning C4191: 'reinterpret_cast' : unsafe conversion from 'FARPROC' to 'TIsWow64ProcessFunction'
Calling this function through the result pointer may cause your program to fail

Если я использую приведение в стиле C, появляется то же самое предупреждение, но теперь оно упоминает «приведение типа» вместо «reinterpret_cast».

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

Как мне обратиться к этим предупреждениям?Нужно ли вносить изменения в мой код?

Ответы [ 3 ]

7 голосов
/ 18 ноября 2010

Вы приводите FARPROC (указатель функции без аргументов) к указателю функции с аргументами.Обычно это очень глупая вещь, которая может привести к повреждению стека.

Теперь выясняется, что GetProcAddress () на самом деле не возвращает FARPROC, и вы действительно знаете, что делаете, но компилятор этого не знает и чувствует себя обязанным предупредить вас.

Единственный способ заставить его замолчать, это использовать #pragma или переключатель компилятора, чтобы отключить предупреждение.Это уродливо и грязно, но это для вас программирование Windows.: -)

6 голосов
/ 18 июля 2016

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

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

У вас есть два хороших варианта:

  1. Подавить каждуюиндивидуальное предупреждение с использованием специфической для MSVC прагмы. В новой строке чуть выше клеветнического приведения добавьте следующий код:

    #pragma warning(suppress: 4191)
    

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

    Итак, альтернативно…

  2. Вы можете отключить предупреждение путем явного приведения результата GetProcAddress (a FARPROC) к void* изатем приведение этого void* к определенному типу указателя на функцию.Например:

    typedef BOOL ( __stdcall *TIsWow64ProcessFunction )( HANDLE, BOOL* );
    
    TIsWow64ProcessFunction isWow64ProcessFunction =
        reinterpret_cast<TIsWow64ProcessFunction>(
           reinterpret_cast<void*>(
           ::GetProcAddress(hInstance, "IsWow64Process")));
    

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

2 голосов
/ 16 ноября 2010

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

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