2010-08-12 32 views
11

Tôi đã có mã mà trông giống như thế này, nơi addr là một sockaddr *:dereferencing con trỏ không phá vỡ quy tắc anti-aliasing nghiêm ngặt sử dụng socket Berkeley

struct sockaddr_in *sin = (struct sockaddr_in *) addr; 
const char *IP=inet_ntoa(sin -> sin_addr); 

Tôi tin rằng đây là mã rất điển hình cho việc sử dụng Berkeley ổ cắm.

Tuy nhiên, khi tôi biên dịch này, tôi nhận được cảnh báo sau đây:
dereferencing pointer 'sin' does break strict anti-aliasing rules

Tìm kiếm trên Internet, tôi tìm thấy một số cuộc thảo luận về thực tế là cách tôi đang làm mọi thứ là khá điển hình, nhưng điều này biên dịch cảnh báo cũng là khá thực tế và không phải là một điều tốt.

Cách thích hợp để làm lại mã này để khắc phục cảnh báo và không chỉ làm im lặng cảnh báo đó là gì?

Trả lời

-2

Nếu tệp tiêu đề và trình biên dịch của bạn là cả hai phần của cùng một bản C hoặc C++, hãy khiếu nại với nhà cung cấp của bạn và yêu cầu họ đặt một tệp #pragma phù hợp trong tệp tiêu đề của họ để tắt trình biên dịch của họ. Là người triển khai, họ được phép chơi các trò chơi như vậy, miễn là họ cung cấp một triển khai phù hợp.

Nếu tệp tiêu đề và trình biên dịch của bạn xuất phát từ hai triển khai C hoặc C++ riêng biệt, bạn may mắn khi mọi thứ hoạt động tốt, và bạn phải tự giải quyết.

+1

Sockets không một phần của việc thực hiện biên dịch nhưng một phần của hệ điều hành. –

+0

Trường hợp lập trình viên có "#include ", thì tệp tiêu đề đó có nội dung gì đó.h là một phần của việc thực hiện C hoặc C++, hoặc người lập trình khác may mắn rằng mọi thứ hoạt động tốt như họ làm và lập trình viên phải tự giải quyết nó. –

+1

Điều đó chỉ đúng đối với #include tệp là một phần của ngôn ngữ, ví dụ: stdlib.h. Ổ cắm bao gồm các tập tin là một phần của một ổ cắm SDK, không phải là trình biên dịch. – EJP

1

Tùy thuộc vào cách bạn đã sử dụng struct sockaddr, tôi cho rằng mã của bạn đã bị hỏng hoặc mã gcc bị hỏng. struct sockaddrstruct sockaddr_in có thành phần ban đầu chung (sa_family/sin_family) để nó không vi phạm quy tắc bí danh nếu bạn chỉ truy cập phần tử này thông qua cả hai con trỏ; làm như vậy được cho phép bởi C99. Hơn nữa, struct sockaddr không có yếu tố nào khác mà bạn được phép truy cập. Nó chủ yếu là một loại đục cho đa hình địa chỉ ổ cắm nguyên thủy. Nếu bạn đã xem xét các nội dung cụ thể trong struct sockaddr, hoặc tệ hơn, nếu bạn khai báo đối tượng struct sockaddr thay vì chỉ là con trỏ hoặc thực hiện sao chép giữa các đối tượng như vậy, mã của bạn bị hỏng. Nếu bạn không làm như vậy và gcc đưa ra cảnh báo tuyên bố rằng bạn đã phá vỡ quy tắc bí danh, thì thế hệ cảnh báo của gcc bị hỏng. Tôi chắc chắn sẽ không ngạc nhiên nếu đó là sau này.

+1

@R. đầu tiên tôi không nghĩ rằng nó được nói rằng 'sa_family/sin_family' là một phần tử ban đầu chung. Họ phải có mặt cả hai, với giá trị giống hệt nhau. Sau đó, truy cập như OP đã cho nó * là * một hành vi vi phạm các quy tắc bí danh, về cơ bản anh ta đang làm '((struct sockaddr_in *) addr) -> sin_addr' mà là một thành ngữ phổ biến để làm những việc như vậy. –

+0

Đúc một con trỏ và sau đó dereferencing nó là, bởi chính nó, ** không bao giờ ** vi phạm các quy tắc răng cưa. Chỉ khi bạn cũng dereferenced nó mặc dù các loại ban đầu có thể răng cưa quy tắc đã bị vi phạm. Bất kể POSIX có đảm bảo rằng '* _family' là một phần tử ban đầu chung hay không, trong thực tế nó ** là ** và gcc, có định nghĩa cấu trúc, biết điều này. Vì vậy, khiếu nại của tôi về không có quy tắc bí danh nào bị vi phạm là chính xác. –

+0

'Chúng phải có mặt cả hai, với các giá trị giống hệt nhau' không có nghĩa gì cả. Bạn đang nói về cùng một mảnh bộ nhớ. Tất nhiên các giá trị đều giống nhau. – EJP

2

Có, đây là vấn đề đã biết với gcc và ổ cắm. Vấn đề về cơ bản dường như là cách mà công cụ ip [46] này được thiết kế không tương thích với các giả định rằng những người gcc nghĩ rằng họ có thể suy luận về răng cưa của con trỏ.

Tôi thường nhận được ngay với điều này bằng cách đầu tiên tham gia một con trỏ trên struct

struct in_addr* act = &(sin->sin_addr); 

và sau đó sử dụng *act.

+1

Nếu gcc không cung cấp cho bạn cảnh báo tương tự khi bạn sử dụng * hành động, hoặc bạn không bật cùng một cảnh báo mà áp phích gốc đã làm hoặc bạn tìm thấy lỗi trong gcc. –

5

Tôi gặp sự cố tương tự - có vẻ như lỗi trong gcc.

tôi đã có thể để có được xung quanh nó bằng cách sử dụng

(*sin).sin_addr 

thay vì

sin->sin_addr 
Các vấn đề liên quan