Я читав різні повідомлення про Stack Overflow 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;
}
Якщо моє розуміння, викладене вище, правильне, a void**
, будучи все ще лише вказівником, це має бути безпечним прийомом.
Чи є спосіб вирішення питання, що не використовується lvalues, які б утихомирили це специфічне для компілятора попередження / помилку? Тобто я розумію, що і чому це вирішить проблему, але я хотів би уникнути такого підходу, тому що я хочу скористатись freeFunc()
НУЛЬНІСТЬМИ передбачуваного виводу:
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**
, будучи ще лише вказівником, це має бути безпечним литтям." Вау там скупий! Здається, у вас є деякі принципові припущення. Постарайтеся думати менше в плані байтів і важелів, а більше - в абстракціях, адже саме це ви насправді програмуєте