Hãy xem xét các chương trình C tầm thường sau,Cách chính xác để xây dựng một thư viện C đa nền tảng, an toàn và chủ đề là gì?
#include <errno.h>
int
main(int argc, char* argv[]) {
return errno;
}
Khi biên soạn trên Solaris, hành vi của mã này là phụ thuộc vào sự hiện diện của -D_REENTRANT
.
solaris$ cc -E test.c | grep return
return errno;
solaris$ cc -D_REENTRANT -E test.c | grep return
return (* (___errno ()));
với phiên bản thứ hai là an toàn chỉ. Nếu chúng ta biên dịch cùng mã trên Linux, chúng tôi nhận được cùng một độc lập hành vi của -D_REENTRANT
linux$ gcc -E test.c | grep return
return (*__errno_location());
linux$ gcc -D_REENTRANT -E test.c | grep return
return (*__errno_location());
Solaris' cc
có quyền lựa chọn -mt
, trong đó hàm ý -D_REENTRANT
, cũng như gcc
's -pthread
. Tuy nhiên, đối với một thư viện, việc chỉ rõ các tùy chọn đa luồng này có vẻ kém, vì nó tiêm một sự phụ thuộc không cần thiết vào thời gian chạy luồng. Tuy nhiên, nếu thư viện cần phải có chủ đề an toàn (bao gồm cả errno), thì ngữ nghĩa chủ đề an toàn là cần thiết ở cả thời gian biên dịch của thư viện và mã bắt nguồn. Trên Linux, điều này là dễ dàng, bởi vì errno luôn là thread-local, nhưng điều đó không được bảo đảm trên các hệ thống khác như vừa được chứng minh.
Kết quả đó trong câu hỏi: thư viện an toàn chủ đề được biên soạn và phân phối đúng cách bằng tiêu đề như thế nào? Một tùy chọn sẽ là #define _REENTRANT
trong tiêu đề chính, nhưng điều này sẽ gây ra sự cố nếu #include <errno.h>
xảy ra trước khi bao gồm tiêu đề thư viện. Một tùy chọn khác là biên dịch thư viện với -D_REENTRANT
và có tiêu đề chính #error
nếu _REENTRANT
không được xác định.
Cách chính xác/tốt nhất để tạo thư viện an toàn cho chủ đề và đảm bảo thư viện hoạt động chính xác với mã được liên kết với nó?
'cc -D_POSIX_C_SOURCE = 200112L -E test.c | grep return -> return (* (___errno())); ' Thật vậy, hoạt động như mong đợi; bạn cũng đề xuất xác định điều này trong tiêu đề của thư viện tương thích POSIX? –
@AlexanderChernyakhovsky: Không, nó không bao giờ cần phải được xác định trong bất kỳ tập tin tiêu đề. Nó phải luôn luôn được định nghĩa ở đầu tệp nguồn. Đó là cách duy nhất để chắc chắn rằng nó được xác định trước khi đưa vào bất kỳ tiêu đề nào. Bạn cũng có thể xác định nó trên dòng lệnh, giống như bạn đã làm trong ví dụ của bạn. Đó là chấp nhận được. Tôi thích nhìn thấy nó trong tập tin nguồn, nhưng đó là một phần chỉ là một vấn đề của hương vị. –
Thú vị. Có vẻ như bạn đang ủng hộ việc kiểm tra '# define' trong tiêu đề thư viện của mình, bởi vì tôi vẫn không muốn một nhà phát triển cuối cùng kết thúc nhận sai errno. –