8

Tại một số điểm tôi nhớ đọc rằng các chủ đề không thể được tạo một cách an toàn cho đến dòng đầu tiên của hàm main(), vì các trình biên dịch chèn mã đặc biệt để thực hiện công việc luồng chạy trong thời gian khởi tạo tĩnh. Vì vậy, nếu bạn có một đối tượng toàn cầu tạo ra một chuỗi đang được xây dựng, chương trình của bạn có thể bị lỗi. Nhưng bây giờ tôi không thể tìm thấy bài viết gốc, và tôi tò mò về sự hạn chế mạnh mẽ như thế nào - nó có đúng theo tiêu chuẩn không? Có đúng trên hầu hết các trình biên dịch không? Nó sẽ vẫn đúng trong C++ 0x? Có thể cho trình biên dịch phù hợp tiêu chuẩn để tự tạo khởi chạy tĩnh chính nó đa luồng không? (ví dụ: phát hiện hai đối tượng toàn cầu không chạm vào nhau, và khởi tạo chúng trên các luồng riêng biệt để đẩy nhanh quá trình khởi động chương trình)Chủ đề có thể được tạo một cách an toàn trong khi khởi tạo tĩnh không?

Chỉnh sửa: Để làm rõ, tôi đang cố gắng cảm nhận việc triển khai thực sự có khác biệt đáng kể không về khía cạnh này, hoặc nếu nó là một cái gì đó tiêu chuẩn giả. Ví dụ, về mặt kỹ thuật, tiêu chuẩn cho phép xáo trộn bố cục của các thành viên thuộc về các bộ định danh truy cập khác nhau (public/protected/etc.). Nhưng không có trình biên dịch tôi biết thực sự làm điều này.

+0

"là nó đúng theo tiêu chuẩn" - tiêu chuẩn C++ 03 không có gì để nói về chủ đề của chủ đề. Các vị trí cần quan tâm đến hành vi hiện tại sẽ là POSIX (tất nhiên là tiêu chuẩn * a *, không phải chuẩn *), MSDN, Boost hoặc các tài liệu cụ thể khác cho trình biên dịch, nền tảng và luồng API sử dụng. –

Trả lời

6

Những gì bạn đang nói về không đúng ngôn ngữ nhưng trong Thư viện thời gian chạy C (CRT).
Để bắt đầu, nếu bạn tạo chuỗi bằng cách sử dụng cuộc gọi gốc như CreateThread() trên cửa sổ thì bạn có thể thực hiện ở bất cứ nơi nào bạn muốn bởi vì nó đi thẳng vào hệ điều hành mà không có sự can thiệp của CRT.
Tùy chọn khác mà bạn thường có là sử dụng _beginthread() là một phần của CRT. Có một số lợi thế khi sử dụng _beginthread() chẳng hạn như có lỗi errno an toàn. Read more about this here. Nếu bạn định tạo chủ đề bằng cách sử dụng _beginthread(), có thể có một số vấn đề vì các khởi tạo cần thiết cho _beginthread() có thể không được đặt đúng chỗ.

Điều này liên quan đến vấn đề chung hơn về những gì diễn ra chính xác trước main() và theo thứ tự nào. Về cơ bản, bạn có chức năng điểm vào của chương trình sẽ xử lý mọi thứ cần thực hiện trước main() với Visual Studio, bạn có thể xem đoạn mã này trong CRT và tìm hiểu chính xác những gì đang xảy ra ở đó. Cách dễ nhất để truy cập mã đó là dừng điểm ngắt trong mã của bạn và xem khung ngăn xếp trước main()

+0

Cảm ơn, điều này mang lại cho tôi một số ý tưởng về tình hình giống như trên Windows với MSVC. Tôi vẫn tò mò về các nền tảng khác mặc dù, và nó không thực sự trả lời cho dù đó là an toàn trên Windows hay không (hiện _beginthread() thực sự dựa vào bất kỳ khởi tạo có thể đã không diễn ra chưa?). –

+0

Tôi ước mình cũng biết điều này. Các tài liệu dường như không đề cập đến nó. – shoosh

2

Vấn đề cơ bản là hạn chế Windows về những gì bạn có thể và không thể thực hiện trong DllMain. Đặc biệt, bạn không được phép tạo chủ đề trong DllMain. Khởi tạo tĩnh thường xảy ra từ DllMain. Sau đó, nó sau một cách logic mà bạn không thể tạo ra các chủ đề trong khi khởi tạo tĩnh.

+1

Nhưng lưu ý: 'Trong quá trình khởi động quá trình và thói quen khởi tạo DLL, chủ đề mới có thể được tạo, nhưng chúng không bắt đầu thực hiện cho đến khi quá trình khởi tạo DLL được thực hiện cho tiến trình' từ http://msdn.microsoft.com/vi-us/library/ms682453% 28v = VS.85% 29.aspx –

+0

Điểm công bằng, không thấy điều đó. Lưu ý rằng chú thích áp dụng riêng cho 'CreateThread', mặc dù' _beginthreadex' không có ngoại lệ này. – MSalters

0

Theo như tôi có thể biết từ việc đọc bản nháp C++ 0x/1x, bắt đầu chuỗi trước main() là tốt, nhưng vẫn phải chịu những cạm bẫy bình thường của khởi tạo tĩnh. Việc triển khai tuân thủ sẽ phải đảm bảo mã để intialize luồng thực hiện trước bất kỳ trình xây dựng tĩnh hoặc luồng nào thực hiện.

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