2013-03-24 15 views
17

Tôi đang sử dụng trình biên dịch C++ của Intel, mà trên Linux dựa trên libc.so do GNU cung cấp và libstdC++.Rủi ro của các phiên bản GCC khác nhau tại thời gian liên kết/chạy?

Đây là vấn đề của tôi. Để có quyền truy cập vào một số tính năng mới nhất của C++ 11, tôi cần sử dụng libstdC++ với GCC 4.7 hoặc cao hơn. Nhưng tôi đang bị mắc kẹt bằng cách sử dụng CentOS 6.4.

Trên CentOS 6.4, phiên bản gốc của GCC là 4.4. Nhưng sử dụng một thứ RedHat gọi là "SCL" và một gói có tên "devtoolset-1.1", tôi có thể cài đặt GCC 4.7 trong "/ opt".

Tôi thiết lập mọi thứ để sử dụng GCC 4.7 theo cách đã đề cập ở trên, tôi có thể sử dụng các tính năng C++ 11 mới hơn.

Vì vậy, đây là câu hỏi của tôi: Nếu người dùng chạy chương trình của tôi chỉ với phiên bản GCC 4.4 libc.so/libstdC++. Vì vậy, trong đường dẫn thư viện, có rủi ro là chương trình của tôi sẽ có lỗi do một số không khớp giữa Phiên bản 4.4 và 4.7 của các thư viện đó?

Nếu có vấn đề tiềm ẩn, tôi có thể làm việc xung quanh nó bằng cách liên kết tĩnh trong các phiên bản libc và libstdC++ của GCC 4.7 không? Hoặc là thiết lập bản thân mình cho các vấn đề khác nếu/khi các thư viện khác mà mã của tôi tự động tải lấy libc/libstdc cũ hơn được cung cấp bởi gói GCC 4.4 toàn hệ thống?

Trả lời

16

Như Praetorian đã chỉ ra trong các nhận xét dưới đây, việc sử dụng bộ công cụ thực sự giải quyết vấn đề tôi đã mô tả ban đầu trong câu trả lời này. Tôi đã sửa câu trả lời.

có rủi ro là chương trình của tôi sẽ có lỗi do không khớp giữa các phiên bản 4.4 và 4.7 của các thư viện đó không?

Có. Liên kết với libstdC++ mới hơn, do đó, sau đó cố gắng chạy với phiên bản cũ hơn thì không hỗ trợ 100%. Nếu bất kỳ đối tượng nào trong chương trình của bạn hoặc bất kỳ thư viện nào nó sử dụng được biên dịch với GCC 4.7 và được liên kết với libstdC++, do đó, từ 4.7 thì bạn cần sử dụng libstdC++, từ 4.7 (hoặc mới hơn) khi chạy. Nó có lẽ thậm chí sẽ không chạy, nhưng nếu nó có thể có lỗi im lặng do không tương thích. Nhưng đó không phải là một vấn đề trong trường hợp của bạn, bởi vì bạn không liên kết với libstdC++ của GCC 4.7, vì vậy, xem bên dưới.

Tôi có thể làm việc xung quanh nó bằng cách liên kết tĩnh trong các phiên bản libc và libstdC++ của GCC 4.7 không?

1) Bạn chỉ cần làm điều đó cho libstdC++, bởi vì không có điều gì như "phiên bản libc của GCC 4.7". Glibc là một dự án hoàn toàn tách biệt với GCC. Khi bạn đang sử dụng GCC 4.7 bạn không sử dụng một libc khác, bạn vẫn đang sử dụng hệ thống libc từ CentOS 6.4. (Như một sang một bên, hãy lưu ý rằng liên kết tĩnh glibc được khuyên dùng bởi các nhà bảo trì glibc, và một số tính năng của glibc sẽ không hoạt động khi được liên kết tĩnh.)

2) Static libstdC++ sẽ làm việc xung quanh vấn đề, nhưng bạn không cần, bởi vì đó là những gì các Red Hat Developer Toolset (devtoolset) không cho bạn anyway. Toàn bộ điểm của devtoolset là nó cho phép bạn sử dụng một GCC mới hơn và libstdC++ mới hơn nhưng không tạo ra bất kỳ phụ thuộc thời gian chạy nào trên thư viện libstdC++ mới hơn. Các tập tin thực thi được biên dịch chỉ cần phiên bản hệ thống của libstdC++, do đó luôn luôn hiện diện trên RHEL/CentOS, thậm chí cả các hệ thống không có cài đặt devtoolset. (Những gì devtoolset làm là gói tất cả các tính năng libstdC++ mới trong một thư viện tĩnh, được gọi là libstdc++_nonshared.a để tất cả các phần không có trong hệ thống libstdC++.vì vậy hãy liên kết tĩnh và mọi thứ khác sẽ đến từ hệ thống libstdC++.

Nếu bạn không sử dụng bộ công cụ devtoolset thì một tùy chọn khác thay vì liên kết tĩnh libstdC++ sẽ gửi mã libstdC++ mới hơn. Vì vậy, với mã của bạn và đảm bảo nó được tìm thấy đầu tiên (ví dụ: bằng cách liên kết mã của bạn với RPATH) mới hơn libstdC++. vậy). Nhưng với devtoolset thì không cần thiết.

Hoặc là thiết lập bản thân mình lên cho các vấn đề khác nếu/khi các thư viện khác mà mã của tôi tự động tải nhặt cũ libc/libstdC++ cung cấp bởi hệ thống toàn GCC 4.4 gói?

Sẽ không có vấn đề gì khi sử dụng bộ công cụ devtoolset vì bạn luôn sử dụng libstdC++ cũ hơn và vì vậy không bao giờ có xung đột.

+0

Cảm ơn. Vì vậy, nó thực sự đơn giản như đảm bảo rằng libstdC++, do đó, từ GCC 4.7 có trong LD_LIBRARY_PATH của tôi trước bất kỳ phiên bản libstdC++ nào khác, do đó, khi chạy một chương trình được xây dựng dựa trên libstdC++? Nó sẽ không gây ra vấn đề nếu một trong những tệp khác .so mà chương trình của tôi sử dụng có sự phụ thuộc liên kết động chống lại libstdC++, nhưng đối tượng được chia sẻ khác được xây dựng dựa trên phiên bản GCC trước đó? (Nó không nhất thiết phải là kết thúc của thế giới nếu đó là trường hợp, bởi vì chương trình của tôi có rất ít (trực tiếp) phụ thuộc vào các thư viện khác.) –

+0

Không, nó sẽ hoạt động tốt. libstdC++ là tương thích ngược, do đó, 'libstdC++. so.6.0.17' từ 4.7 có thể được sử dụng bởi bất cứ thứ gì được biên dịch với 4.7 hoặc cũ hơn (quay lại GCC 3.4.0, dù sao) nhưng nó không ** tương thích về phía trước, do đó, 'libstdC++. so.6.0.13' từ 4.4 không thể được sử dụng bởi một cái gì đó được biên dịch với 4.7 –

+0

NB Hiện tại không có sự đảm bảo nào về tính tương thích của C++ 11 giữa các bản phát hành libstdC++, vì vậy nếu các thư viện khác mà mã của bạn tải sử dụng các tính năng C++ 11 thì chúng sẽ được biên dịch lại với 4.7, nhưng nếu chúng chỉ sử dụng các tính năng của C++ 03 thì libstdC++ mới hơn sẽ hoạt động tốt. –