Czytałem różne posty na temat Przepełnienia stosu RE: dereferujący błąd wskaźnika pisanego czcionką typu. Rozumiem, że błąd jest zasadniczo ostrzeżeniem kompilatora o niebezpieczeństwie dostępu do obiektu za pomocą wskaźnika innego typu (choć wydaje się, że istnieje wyjątek char*
), co jest zrozumiałym i rozsądnym ostrzeżeniem.
Moje pytanie jest specyficzne dla poniższego kodu: dlaczego przesłanie adresu wskaźnika do void**
kwalifikującego się do tego ostrzeżenia (awansowane przez błąd -Werror
)?
Co więcej, ten kod jest kompilowany dla wielu architektur docelowych, z których tylko jedna generuje ostrzeżenie / błąd - czy może to sugerować, że jest to uzasadniony brak specyficzny dla wersji kompilatora?
// 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;
}
Jeśli moje rozumienie, o którym mowa powyżej, jest poprawne, a void**
będąc nadal tylko wskaźnikiem, powinno to być bezpieczne rzucanie.
Czy istnieje obejście, w którym nie stosuje się wartości lv, które uspokoją to ostrzeżenie / błąd specyficzne dla kompilatora? Tzn. Rozumiem to i dlaczego to rozwiązuje problem, ale chciałbym uniknąć tego podejścia, ponieważ chcę skorzystać z freeFunc()
NULL w zamierzonym out-arg:
void* tmp = f;
freeFunc( &tmp );
f = NULL;
Kompilator problemów (jeden z jednego):
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$
Nie narzekający kompilator (jeden z wielu):
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$
Aktualizacja: Odkryłem, że ostrzeżenie wydaje się być generowane specjalnie po kompilacji -O2
(nadal tylko z zaznaczonym „kompilatorem problemów”)
void**
, będąc wciąż tylko wskaźnikiem, powinien to być bezpieczny rzut”. Wow, pomijam! Wygląda na to, że masz pewne podstawowe założenia. Staraj się mniej myśleć w kategoriach bajtów i dźwigni, a więcej w kategoriach abstrakcji, ponieważ tak właśnie programujesz