2013-04-15 31 views
14

Tôi tự hỏi rằng có thể chắc chắn trật tự giữa sự tàn phá của đối tượng toàn cầu và atexit trong C++thứ tự giữa sự tàn phá của đối tượng toàn cầu và atexit trong C++

Tôi có một đối tượng toàn cầu và đăng ký atexit chức năng như dưới đây:

static MyClass g_class; 

void onExit() 
{ 
    // do some destruction 
} 

int main() 
{ 
    atexit(onExit); 

    return 0; 
} 

Tôi đã tìm thấy onExit() được gọi trước MyClass::~MyClass() trong Visual Studio 2012 và gcc4.7.2. Tôi có chắc rằng onExit luôn được gọi trước khi đối tượng toàn cầu (như g_class) hủy diệt?

Tôi tự hỏi đăng ký đối tượng toàn cầu và atexit đơn đặt hàng đăng ký sử dụng cùng một bảng thứ tự. Hoặc không có mối quan hệ nào giữa thứ tự đối tượng toàn cầu và đơn đặt hàng atexit?

Đã chỉnh sửa: Xin lỗi tôi đã viết nhầm. Tôi rất bối rối trong khi làm sạch mã ví dụ. onExit() được gọi trước ~ MyClass().

+0

Tôi nghi ngờ đơn đặt hàng đó không chắc chắn 100%. Bạn quan tâm làm gì? –

+0

Tạo một đối tượng toàn cầu khác trước 'MyClass' và gọi' atexit (onExit) 'trong hàm tạo của nó để kiểm tra. – lapk

+1

Muốn kiểm soát tuổi thọ của các đối tượng, hãy sử dụng các đối tượng động. – PiotrNycz

Trả lời

14

CẬP NHẬT:OP gây nhầm lẫn và dường như VC11 thực sự hoạt động như được chỉ định trong tiêu chuẩn C++ 11. Câu trả lời sau được viết bằng giả định rằng nó không.

Do đó, câu trả lời cho câu hỏi này:

Tôi chắc chắn rằng onExit luôn gọi trước khi đối tượng toàn cầu (như g_class) phá hủy?

"Yes", miễn là bạn đang làm việc với một trình biên dịch hoàn toàn tuân thủ.


tôi đã tìm thấy MyClass::~MyClass() được gọi trước khi onExit() trong Visual Studio 2012.

Nếu đây là trường hợp, sau đó nó là một lỗi trong VC11. Mỗi khoản 3.6.3/1 của C++ 11 Tiêu chuẩn:

Destructors (12,4) cho các đối tượng khởi tạo (có nghĩa là, các đối tượng suốt đời mà (3.8) đã bắt đầu) với lưu trữ tĩnh thời gian được gọi là một kết quả của việc quay trở lại từ main và kết quả là gọi số std::exit (18.5). [...]

Ngoài ra, theo khoản 3.6.3/3:

Nếu khi hoàn thành việc khởi tạo một đối tượng với thời gian lưu trữ tĩnh được giải mã trước khi một cuộc gọi để std::atexit (xem <cstdlib>, 18.5), cuộc gọi đến chức năng được chuyển đến std::atexit được sắp xếp thứ tự trước khi cuộc gọi đến trình phá hủy cho đối tượng.

Vì vậy, trong trường hợp của bạn, onexit() phải được gọi trước hủy của MyClass.

Theo như tôi có thể nói, Clang 3.2 và GCC 4.8.0 tuân thủ theo khía cạnh này, như được nêu trong live example này.

+0

Cho dù g ++ có tuân thủ hay không phụ thuộc vào tùy chọn trình biên dịch và nền tảng. (Nó tuân thủ khi nó có thể được, nhưng kể từ trên nhiều nền tảng, chức năng 'atexit' được cung cấp bởi nền tảng, nó không phải luôn luôn hợp lý có thể.) –

+0

xin lỗi. Tôi đã viết một sai lầm. onexit() được gọi trước ~ MyClass. Tôi đã rất bối rối trong khi làm sạch mã ví dụ. – zelon

+2

@zelon: OK. Sau đó, hành vi là chính xác và đây là những gì C++ Standard chỉ định. –

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