2010-06-28 47 views
19

Tôi đang biên soạn một số C++ mã trong MinGW GCC 4.4.0, và nhận được lời cảnh báo với các hình thức sau đây ...Điều gì là sai với việc sử dụng offsetof này?

warning: invalid access to non-static data member '<membername>' of NULL object 
warning: (perhaps the 'offsetof' macro was used incorrectly) 

vấn đề này có vẻ quen thuộc - một cái gì đó tôi đã cố gắng để giải quyết trước và thất bại, tôi suy nghĩ, nhưng một lúc trước. Mã xây dựng tốt trong Visual C++, nhưng tôi đã không xây dựng mã đặc biệt này gần đây trong bất kỳ trình biên dịch khác.

Mã vấn đề là các mẫu sau đây ...

template<typename T> 
class c_Align_Of 
{ 
    private: 
    struct c_Test 
    { 
     char m_Char; 
     T m_Test; 
    }; 
    public: 
    enum { e_Align = offsetof (c_Test, m_Test) }; 
}; 

Rõ ràng tôi có lẽ có thể sử dụng một số tổng hợp có điều kiện để sử dụng chức năng biên dịch cụ thể cho điều này, và tôi tin rằng C++ 0x sẽ (sau cùng) làm cho nó thừa. Nhưng trong mọi trường hợp, tôi không thể nhìn thấy bất cứ điều gì sai trái với việc sử dụng này của offsetof.

Rất vẻ thông thái, có thể là vì T loại tham số đôi khi không POD, các lớp học để GCC c_Test như phi POD và than phiền (và than phiền và phàn nàn - Tôi nhận được gần 800 dòng những cảnh báo này) .

Điều này là nghịch ngợm bởi các từ ngữ nghiêm ngặt của tiêu chuẩn, vì các loại không thuộc POD có thể vi phạm offsetof. Tuy nhiên, loại hình không phải POD này không phải là vấn đề trong thực tế - c_Test sẽ không có bảng ảo và không cần phải thực hiện thủ đoạn thời gian chạy để tìm bù đắp của m_Test.

Bên cạnh đó, ngay cả khi c_Test có bảng ảo, GCC triển khai macro offsetF bằng nội tại luôn được đánh giá tại thời gian biên dịch dựa trên bố cục tĩnh của loại cụ thể đó. Cung cấp một công cụ sau đó rên rỉ (xin lỗi, cảnh báo) mỗi khi nó được sử dụng chỉ có vẻ ngớ ngẩn.

Ngoài ra, tôi không phải là người duy nhất quanh đây ai làm loại điều ...

Answer to legit-uses-of-offsetof question

tôi làm nhớ mình có một vấn đề với offsetof cho loại lý do, nhưng Tôi không nghĩ rằng sự cố là mẫu này.

Bất kỳ ý tưởng nào?

+0

Bạn có thể thêm ví dụ cho các loại POD tái tạo sự cố không? –

+0

@Georg - Không có vấn đề gì - tôi không nghĩ thẳng. Họ có các nhà thầu và do đó không phải là POD. Xem câu trả lời dưới đây. – Steve314

Trả lời

33

Rất tiếc ...

Vấn đề với c_Test struct là phi POD do loại T là phi POD. Dưới đây là một trích dẫn từ tài liệu GCC ...

-Wno-invalid-offsetof (C++ và Objective-C++ chỉ)

cảnh báo Suppress từ việc áp dụng 'offsetof' vĩ mô để một-POD không loại .

Theo tiêu chuẩn ISO C++ năm 1998, áp dụng ‘offsetof’ cho loại không phải POD không được xác định. Tuy nhiên, trong các triển khai C++ hiện tại, ‘bù đắp’ thường mang lại kết quả có ý nghĩa ngay cả khi được áp dụng cho một số loại nhất định không phải loại POD. (Chẳng hạn như 'cấu trúc' đơn giản không phải là loại POD chỉ nhờ có một hàm tạo .) Cờ này là dành cho người dùng , người nhận thức được rằng họ đang viết mã không thể di chuyển và được chọn bỏ qua cảnh báo về điều đó.

Các hạn chế đối với ‘offsetof’ có thể là thư giãn trong phiên bản tương lai của tiêu chuẩn C++ .

Vấn đề của tôi là hầu như tất cả các loại T đều có nhà thầu và do đó được phân loại là không phải POD. Tôi bỏ qua điểm này là không liên quan trước đó - và tất nhiên nó không liên quan đến offsetof về nguyên tắc. Vấn đề là tiêu chuẩn C++ sử dụng phân loại POD so với không POD mặc dù có một số cách khác nhau không phải là POD và trình biên dịch là đúng để cảnh báo về việc sử dụng không tuân thủ theo tiêu chuẩn theo mặc định.

Giải pháp của tôi cho thời điểm này sẽ là tùy chọn ở trên để ngăn chặn cảnh báo - bây giờ tôi chỉ cần tìm ra cách nói cho cmake sử dụng nó.

+0

Tôi cảm thấy tội lỗi khi chấp nhận điều này - có lẽ tôi nên hoàn tác và xóa câu hỏi thay thế? – Steve314

+9

Phạt tiền của nó vì nó thực sự trả lời câu hỏi của bạn - những người khác có thể mắc phải sai lầm tương tự. Thậm chí còn có [huy hiệu] (http://stackoverflow.com/badges/14/self-learner) khuyến khích điều này :) –

+1

giải pháp cmake: 'set (CMAKE_CXX_FLAGS" $ {CMAKE_CXX_FLAGS} -Không có giá trị không hợp lệ ") ' – doug65536

-2

Cũng giải thích ngây thơ về lỗi cụ thể này là lấy nó theo mệnh giá: Bạn truy nhập một trường riêng tư từ bên trong một enum. Nhưng có lẽ, enums là tĩnh theo định nghĩa (tôi cho rằng đây là lý do tại sao làm việc với hằng số enum là có thể ở nơi đầu tiên, họ về cơ bản int hằng với một tên ưa thích).

+0

Enum là thành viên của lớp. Thành viên của một lớp học được phép tham khảo các thành viên tư nhân của cùng một lớp, hoặc người nào khác bạn có thể sử dụng bất kỳ thành viên riêng tư nào không? Không có vấn đề ẩn dữ liệu ở đây - nhưng, tốt, hãy xem câu trả lời của tôi (hơi lúng túng), sẽ xuất hiện sau vài phút ... – Steve314

Các vấn đề liên quan