Eu li várias postagens no Stack Overflow RE: o erro de ponteiro com punção de tipo drefercing. Entendo que o erro é essencialmente o aviso do compilador sobre o perigo de acessar um objeto através de um ponteiro de um tipo diferente (embora uma exceção pareça ter sido feita char*
), que é um aviso compreensível e razoável.
Minha pergunta é específica para o código abaixo: por que converter o endereço de um ponteiro para uma void**
qualificação para esse aviso (promovido a erro via -Werror
)?
Além disso, esse código é compilado para várias arquiteturas de destino, apenas uma delas gera o aviso / erro - isso pode significar que é legitimamente uma deficiência específica da versão do compilador?
// 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;
}
Se meu entendimento, exposto acima, estiver correto, a void**
, ainda sendo apenas um indicador, isso deve ser uma transmissão segura.
Existe uma solução alternativa que não use lvalues que pacifique esse aviso / erro específico do compilador? Ou seja, eu entendo isso e por que isso resolverá o problema, mas gostaria de evitar essa abordagem porque quero tirar proveito do freeFunc()
NULL de um argumento pretendido:
void* tmp = f;
freeFunc( &tmp );
f = NULL;
Compilador de problemas (um de um):
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$
Compilador que não reclama (um de muitos):
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$
Atualização: Descobri ainda que o aviso parece ser gerado especificamente quando compilado com -O2
(ainda com o "compilador de problemas" observado apenas)
void**
, ainda sendo apenas um ponteiro, esse deve ser um lançamento seguro". Woah lá skippy! Parece que você tem algumas suposições fundamentais em andamento. Tente pensar menos em termos de bytes e alavancas e mais em termos de abstrações, porque é isso que você está realmente a programação com