2012-01-24 31 views
7

Chúng tôi có một mã được viết bằng C đôi khi không xử lý con trỏ bằng 0.Xử lý con trỏ null trên AIX với GCC C

Mã ban đầu được viết trên Solaris và các con trỏ như vậy gây ra lỗi phân đoạn. Không lý tưởng nhưng tốt hơn là cày.

Kinh nghiệm của chúng tôi là nếu bạn đọc từ con trỏ rỗng trên AIX bạn nhận được 0. Nếu bạn sử dụng trình biên dịch xlc, bạn có thể thêm tùy chọn -qcheck=all để bẫy các con trỏ này. Nhưng chúng tôi sử dụng gcc (và muốn tiếp tục sử dụng trình biên dịch đó). Có gcc cung cấp tùy chọn này không?

+1

Ý của bạn là gì bởi "không xử lý con trỏ bằng 0"? –

+3

Cá nhân tôi xem xét tất cả các tham chiếu đến NULL (mà về mặt kỹ thuật là '0') là lỗi, và sẽ thêm mã để kiểm tra điều đó thay vì tin tưởng trình biên dịch để làm điều đó cho tôi. Đặc biệt là kể từ khi trình biên dịch không biết những gì tôi muốn làm gì nếu có một con trỏ 'NULL'? Đôi khi bạn có thể bỏ qua mã truy cập con trỏ, đôi khi đó là lỗi nghiêm trọng cần phải hủy bỏ chương trình. –

+1

AFAIK dereferencing một con trỏ NULL dẫn đến hành vi không xác định. –

Trả lời

6

Gcc có cung cấp tùy chọn như vậy không?

Tôi đang ngượng ngùng tình nguyện trả lời không, nó không. Mặc dù tôi không thể trích dẫn số vắng mặt thông tin về séc gcc và thời gian chạy NULL.

Vấn đề bạn đang giải quyết là bạn đang cố gắng thực hiện hành vi không xác định một chút được xác định trong chương trình kém được viết.

Tôi khuyên bạn nên cắn viên đạn và chuyển sang xlc hoặc tự thêm NULL kiểm tra mã cho đến khi tìm thấy và xóa hành vi xấu.

xem xét:

  • Làm một macro để null-kiểm tra một con trỏ
  • Thêm rằng macro sau khi tập con trỏ
  • Thêm rằng macro để điểm vào các chức năng chấp nhận gợi ý

Khi lỗi được xóa, bạn có thể bắt đầu xóa các kiểm tra này.

2
  1. Vui lòng ủng hộ và thêm thích hợp NULL kiểm tra mã của bạn. Không chỉ bạn sẽ có được một chút trong hiệu suất bằng cách kiểm tra cho NULL chỉ khi cần thiết, thay vì có trình biên dịch thực hiện kiểm tra ở khắp mọi nơi, nhưng mã của bạn sẽ được di động hơn cho các nền tảng khác. Và chúng ta không đề cập đến thực tế rằng bạn sẽ có nhiều khả năng in một thông báo lỗi thích hợp hơn là có trình biên dịch thả một số stack/mã nguồn vị trí/mã lỗi không thể hiểu được sẽ không giúp người dùng của bạn ở tất cả.

  2. AIX sử dụng khái niệm về trang NULL. Về cơ bản, NULL (tức là địa chỉ ảo 0x0) được ánh xạ tới một vị trí chứa toàn bộ số không. Điều này cho phép mã thao tác chuỗi e.t.c. tiếp tục mặc dù gặp phải con trỏ NULL.

    Điều này trái với hầu hết các hệ thống giống Unix khác, nhưng nó không vi phạm tiêu chuẩn C, xem xét dereferencing NULL là hoạt động chưa xác định. Theo ý kiến ​​của tôi, mặc dù, điều này là hư hỏng bị hỏng: nó có một ứng dụng sẽ sụp đổ dữ dội và biến nó thành một trong đó bỏ qua các lỗi lập trình âm thầm, có khả năng tạo ra kết quả hoàn toàn không chính xác.

  3. Theo như tôi biết, GCC không có tùy chọn để làm việc xung quanh mã bị phá vỡ về cơ bản. Ngay cả các mẫu được hỗ trợ trong lịch sử, chẳng hạn như các chuỗi ký tự có thể ghi, đã được loại bỏ dần trong các phiên bản GCC mới hơn.

    Có thể có một số hỗ trợ khi sử dụng tùy chọn gỡ lỗi bộ nhớ như -fmudflap, nhưng tôi thực sự không biết - trong mọi trường hợp bạn không nên sử dụng mã gỡ lỗi trong hệ thống sản xuất, đặc biệt là để buộc mã bị hỏng hoạt động.

Bottom line: Tôi không nghĩ rằng bạn có thể tránh thêm rõ ràng NULL kiểm tra.

Thật không may, bây giờ chúng tôi đến câu hỏi cơ bản: Bạn nên thêm kiểm tra NULL ở đâu?. Tôi cho rằng có trình biên dịch thêm kiểm tra như vậy bừa bãi sẽ giúp, miễn là bạn thêm một kiểm tra rõ ràng khi bạn phát hiện ra một vấn đề.

Thật không may, không có hỗ trợ Valgrind cho AIX. Nếu bạn có tiền mặt, bạn có thể muốn xem xét IBM Rational Purify Plus cho AIX - nó có thể bắt các lỗi như vậy.

Cũng có thể sử dụng xlc trên hệ thống thử nghiệm và gcc cho mọi thứ khác, nhưng tiếc là chúng không hoàn toàn tương thích.