Tôi đã đọc nhiều bài viết khác nhau về Stack Overflow RE: lỗi con trỏ bị trừng phạt loại. Tôi hiểu rằng lỗi về cơ bản là cảnh báo trình biên dịch về sự nguy hiểm của việc truy cập một đối tượng thông qua một con trỏ thuộc loại khác (mặc dù có một ngoại lệ được tạo ra char*
), đây là một cảnh báo dễ hiểu và hợp lý.
Câu hỏi của tôi là cụ thể cho mã dưới đây: tại sao việc chuyển địa chỉ của một con trỏ thành void**
đủ điều kiện cho cảnh báo này (được quảng cáo thành lỗi thông qua -Werror
)?
Hơn nữa, mã này được biên dịch cho nhiều kiến trúc đích, chỉ một trong số đó tạo ra cảnh báo / lỗi - điều này có thể ngụ ý rằng nó là một sự thiếu sót cụ thể của phiên bản trình biên dịch?
// 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;
}
Nếu sự hiểu biết của tôi, được nêu ở trên, là chính xác, a void**
, vẫn chỉ là một con trỏ, đây sẽ là đúc an toàn.
Có một cách giải quyết không sử dụng các giá trị sẽ làm dịu cảnh báo / lỗi cụ thể của trình biên dịch này không? Tức là tôi hiểu điều đó và tại sao điều này sẽ giải quyết vấn đề, nhưng tôi muốn tránh cách tiếp cận này vì tôi muốn tận dụng lợi thế của freeFunc()
NULL trong một dự định ngoài luồng:
void* tmp = f;
freeFunc( &tmp );
f = NULL;
Trình biên dịch vấn đề (một trong một):
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$
Trình biên dịch không phàn nàn (một trong nhiều):
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$
Cập nhật: Tôi đã phát hiện thêm cảnh báo dường như được tạo cụ thể khi được biên dịch bằng -O2
(chỉ với "trình biên dịch sự cố" đã lưu ý)
void**
, vẫn chỉ là một con trỏ, đây nên là đúc an toàn." Ái chà có skippy! Âm thanh như bạn có một số giả định cơ bản đang diễn ra. Cố gắng suy nghĩ ít hơn về byte và đòn bẩy và nhiều hơn về mặt trừu tượng, bởi vì đó là những gì bạn thực sự đang lập trình với