Я читал различные сообщения о переполнении стека RE: ошибка разыменовывающего указателя типа. Насколько я понимаю, ошибка, по сути, является предупреждением компилятора об опасности доступа к объекту через указатель другого типа (хотя, похоже, для этого сделано исключение char*
), что является понятным и разумным предупреждением.
Мой вопрос относится к приведенному ниже коду: почему приведение адреса указателя к void**
значению квалифицируется для этого предупреждения (повышается до ошибки через -Werror
)?
Более того, этот код скомпилирован для нескольких целевых архитектур, только одна из которых генерирует предупреждение / ошибку - может ли это означать, что это законно является недостатком конкретной версии компилятора?
// main.c
#include <stdlib.h>
typedef struct Foo
{
int i;
} Foo;
void freeFunc( void** obj )
{
if ( obj && * obj )
{
free( *obj );
*obj = NULL;
}
}
int main( int argc, char* argv[] )
{
Foo* f = calloc( 1, sizeof( Foo ) );
freeFunc( (void**)(&f) );
return 0;
}
Если мое понимание, изложенное выше, является правильным, то void**
, будучи все еще просто указателем, это должно быть безопасное приведение.
Есть ли обходной путь, не использующий lvalues, который бы успокоил это специфичное для компилятора предупреждение / ошибку? Т.е. я понимаю, что и почему это решит проблему, но я хотел бы избежать этого подхода, потому что я хочу использовать freeFunc()
NULL для получения предполагаемого out-arg:
void* tmp = f;
freeFunc( &tmp );
f = NULL;
Компилятор проблемы (один из одного):
user@8d63f499ed92:/build$ /usr/local/crosstool/x86-fc3/bin/i686-fc3-linux-gnu-gcc --version && /usr/local/crosstool/x86-fc3/bin/i686-fc3-linux-gnu-gcc -Wall -O2 -Werror ./main.c
i686-fc3-linux-gnu-gcc (GCC) 3.4.5
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
./main.c: In function `main':
./main.c:21: warning: dereferencing type-punned pointer will break strict-aliasing rules
user@8d63f499ed92:/build$
Компилятор без жалоб (один из многих):
user@8d63f499ed92:/build$ /usr/local/crosstool/x86-rh73/bin/i686-rh73-linux-gnu-gcc --version && /usr/local/crosstool/x86-rh73/bin/i686-rh73-linux-gnu-gcc -Wall -O2 -Werror ./main.c
i686-rh73-linux-gnu-gcc (GCC) 3.2.3
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
user@8d63f499ed92:/build$
Обновление: я также обнаружил, что предупреждение, похоже, генерируется специально при компиляции -O2
(все еще с отмеченным только "проблемным компилятором")
void**
, оставаясь просто указателем, это должно быть безопасное приведение». Вау там скиппи! Похоже, у вас есть некоторые фундаментальные предположения. Постарайтесь меньше думать с точки зрения байтов и рычагов и больше с точки зрения абстракций, потому что это то, с чем вы на самом деле программируете