2016-11-02 16 views
8

Tôi muốn hiểu chính xác lý do macro hiển thị libC++ cho hàm nội tuyến sử dụng __forceinline hoặc __attribute__((__always_inline__)) như một phần của thuộc tính mà nó liên kết với các hàm nội dòng.Tại sao libcxx áp dụng __forceinline hoặc GCC tương đương với các hàm nội tuyến đã ẩn của nó?

Đối với nền xem:

Nếu các chức năng nội tuyến sẽ được đánh dấu là __visibility__("hidden") dù sao, tại sao nó cần thiết để bổ sung buộc các trình biên dịch để inline họ ?

Tôi đã suy nghĩ về nó một chút, và tôi có một vài giả thuyết, nhưng không ai có vẻ hoàn toàn thỏa đáng với tôi:

  • Nó là để đảm bảo rằng các biểu tượng không vô tình trở thành một phần của ABI. Nếu, trong khi xây dựng thư viện, trình biên dịch đã chọn không inline chức năng, nó có khả năng có thể trở thành một biểu tượng bên ngoài, và do đó một phần của ABI. Nhưng không phải thuộc tính hidden là đủ? Tương tự như vậy, nó sẽ không chỉ cần thiết để buộc nội tuyến chức năng khi xây dựng thư viện? Người tiêu dùng không nên quan tâm.
  • Để đảm bảo rằng hàm không bao giờ có định nghĩa, để tránh các vấn đề ODR, nơi trình biên dịch không muốn nội tuyến hàm trong chính thư viện và không cho phép nội tuyến trong hàm trong mã do khách hàng tạo thư viện, dẫn đến hai định nghĩa khác nhau. Nhưng đó không phải là kết quả mong đợi (và được chấp nhận) của việc sử dụng visibility("hidden")?
  • Nó là một cái gì đó cụ thể cho việc thiết kế libC++ như một thực hiện của thư viện chuẩn.

Tôi hỏi điều này vì tôi đang xây dựng thư viện C++ mà tôi hy vọng một ngày nào đó sẽ tiêu chuẩn hóa ABI và tôi đang sử dụng libC++ làm hướng dẫn. Cho đến nay, nó đã làm việc tốt, nhưng vấn đề này đã gây ra một số đầu gãi.

Cụ thể, chúng tôi đã có báo cáo về người dùng phàn nàn rằng MSVC đã từ chối tôn trọng thuộc tính __forceinline, dẫn đến cảnh báo. Giải pháp được đề xuất của chúng tôi là mở rộng tương tự của chúng tôi thành INLINE_VISIBILITY chỉ bao gồm __forceinline (hoặc tương đương GCC) khi xây dựng thư viện, giả sử giải thích đầu tiên ở trên.

Tuy nhiên, vì chúng tôi không hoàn toàn tin tưởng rằng chúng tôi hiểu lý do đằng sau buộc các chức năng nội tuyến là __forceinline hoặc __attribute__((__always_inline__)) ngay từ đầu, chúng tôi hơi lưỡng lự khi áp dụng giải pháp này.

Bất cứ ai có thể cung cấp câu trả lời dứt khoát cho lý do tại sao libC++ cảm thấy cần phải ép nội tuyến các hàm nội tuyến của nó, mặc dù chúng đã được trang trí là có khả năng hiển thị ẩn?

Trả lời

4

Tôi có thể ở vị trí tốt nhất để giải quyết vấn đề này vì tôi là người đã làm điều đó. Và bạn có thể không thích câu trả lời. :-)

Khi tôi tạo libC++, mục tiêu duy nhất của tôi là macOS (OS X). Đây là cách trước khi libC++ được mở nguồn. Và động cơ chính của tôi cho việc buộc nội tuyến là kiểm soát ABI của dylib sẽ bị đẩy ra với các bản phát hành hệ điều hành. Một chức năng nội tuyến bắt buộc sẽ không bao giờ xuất hiện trong một dylib, và do đó tôi có thể dựa vào nó sống độc quyền trong một tiêu đề (trong đó có một hệ thống phân phối khác với bản phát hành hệ điều hành).

Tôi chưa bao giờ coi thuộc tính bổ sung là "ẩn" như một phần của quyết định này bởi vì nó chỉ đơn giản là một biến chứng không cần thiết đối với tôi. Tôi muốn các chức năng để sống trong một tiêu đề, và không bao giờ được đưa vào một dylib và đó là điều đó. Vì vậy, viên đạn đầu tiên của bạn là tôi tin đúng.

Tôi vui mừng rằng libC++ đã phát triển vượt ra ngoài phạm vi ban đầu của nó và tôi muốn bạn là người giỏi nhất trong việc tiếp tục nỗ lực đó. Tôi rất sẵn lòng cung cấp bất kỳ thông tin bổ sung nào mà tôi có thể phải hỗ trợ bạn trong mục tiêu của bạn.

+0

Tôi thích câu trả lời đó và cảm ơn bạn đã dành thời gian trả lời. Có vẻ như chúng ta có thể tiến lên và đánh giá lại liệu việc nuôi cấy __forceinline của chúng ta là không cần thiết và cần được loại bỏ. Nghe có vẻ như nó có thể là tốt. Ngoài ra, nếu bạn quan tâm đến việc thấy cách tiếp cận mà chúng tôi đang thực hiện hoặc cung cấp bất kỳ phản hồi nào, thư viện được đề cập là libmongocxx: https://github.com/mongodb/mongo-cxx-driver/tree/master – acm

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