2008-10-17 35 views
5

Tôi đang làm việc trên cơ sở mã lớn, cũ kỹ cho ứng dụng MFC. Mã này đã được nhiều nhà phát triển làm việc theo thời gian, và kết quả là, chúng tôi có ba cách khác nhau trong toàn bộ mã giao dịch với khả năng thất bại phân bổ mới.Làm các thư viện tĩnh C++ không có mfc được liên kết với một dự án MFC ném bad_alloc hoặc CMemoryException *?

Cách đầu tiên là kiểm tra NULL trên kết quả mới. Chúng tôi không sử dụng nothrownew.obj vì vậy đây rõ ràng là một lỗi cần được dọn dẹp.

Thứ hai là bắt CMemoryException * (có, ngoại lệ C++ được bật trong trình biên dịch). Từ những gì tôi hiểu, MFC sẽ ghi đè lên toán tử chuẩn mới và thay vào đó ném điều này. Tôi khá chắc chắn rằng phương pháp thứ hai này là chính xác trong ứng dụng MFC chính nó. MFC ghi đè mới, với phiên bản ném CMemoryException lạ của nó.

Cuối cùng đến từ cơ sở của chúng tôi những người tốt với C++, nhưng không phải là lập trình MFC không cần thiết. Họ đang bắt const std :: bad_alloc &.

Điều tôi thực sự không biết là những gì mong đợi đối với các thư viện tĩnh được liên kết trong ứng dụng. Đây là phần lớn mã sử dụng bad_alloc. Giả sử các thư viện này không được biên soạn với MFC hoặc ATL, và được viết bằng chuẩn C++, chúng có thể mong đợi để bắt bad_alloc không? Hay sự hiện diện của MFC trong ứng dụng mà chúng liên kết để lây nhiễm chúng với toán tử mới toàn cầu và làm cho các nỗ lực của chúng thất bại trong việc phân phối không đúng?

Nếu bạn có câu trả lời, bạn có thể giải thích cách thức hoạt động hay chỉ cho tôi tham chiếu đúng để sắp xếp điều này không?

Trả lời

3

Nó sẽ phụ thuộc vào các tùy chọn biên dịch cho các thư viện tĩnh được liên kết với ứng dụng.

Nếu thư viện được biên dịch bằng cấu hình để sử dụng thời gian chạy tĩnh chuẩn C++ sau đó tôi mong đợi operator new từ thời gian chạy chuẩn C++ được gọi.

Nếu thư viện được biên soạn với một cấu hình để sử dụng các tiêu chuẩn C++ run-time DLL thì độ phân giải của các chức năng này sẽ bị trì hoãn cho đến khi tải chương trình và nên được giải quyết đến thay thế MFC của operator new.

Tôi cũng bao gồm liên kết tới Herb Sutter article về lỗi phân bổ xử lý mà bạn có thể thấy hữu ích.

+0

Cảm ơn bạn! Chúng tôi liên kết với thời gian chạy C++ chuẩn như một DLL, có nghĩa là ngoại lệ MFC cho tất cả mọi người. Thật không may, một trong những mục tiêu chính của ứng dụng này là một hệ thống không có bộ nhớ ảo, vì vậy việc kiểm tra phân bổ là bắt buộc, ugh. –

+0

Nếu bạn có thể biên dịch với các biểu tượng thì tôi khuyên bạn nên bước vào cuộc gọi đến toán tử mới và trình gỡ lỗi sẽ chứng minh dứt khoát việc triển khai thực hiện nào đang được gọi. Không chắc chắn nếu đó là hữu ích cho tho nền tảng mục tiêu của bạn .. – Henk

+0

Ký hiệu là không có vấn đề. Buộc các chi nhánh để ném một ngoại lệ, cho thấy kết luận rằng CMemoryException * đang được ném. Điều đó làm cho mọi thứ trở nên phức tạp, nhưng thật tốt khi biết những gì đang diễn ra. Cảm ơn một lần nữa! –

1

Xin chúc mừng - có vẻ như bạn đã có tất cả chúng tôi. :-)

Về lý thuyết, nếu MFC cung cấp quá tải cho hàm new toàn cầu, thì nó phải được sử dụng bởi tất cả mã trong chương trình. Nhưng kể từ khi các thư viện tĩnh được biên dịch mà không biết về điều đó, tôi không thể nói chắc chắn rằng nó sẽ.

Điều tốt nhất tôi có thể đề xuất là viết một số mã thử nghiệm để tìm hiểu. (Tôi sẽ không có quyền truy cập vào hệ thống Windows của mình trong vài giờ tới, hoặc tôi sẽ tự mình làm như vậy và cung cấp cho bạn câu trả lời.)

+0

Điều này làm cho đồng nghiệp của tôi trở nên tồi tệ và không ai có thể tìm ra cách tốt để buộc mới phải thất bại mà không quá tải mới ở nơi đầu tiên. Arg :) –

0

Bạn có thể thay đổi hành vi ném MFC với AfxSetNewHandler(_PNH pfnNewHandler) và cung cấp con trỏ tới chức năng NewHandler của riêng bạn. Chức năng này sau đó sẽ ném một ngoại lệ std::bad_alloc. Nhưng bây giờ các bộ phận MFC-chương trình có vấn đề để bắt một std::bad_alloc.

1

Tôi đã thực hiện một số MFC-Code-Research (trong VC2010). Đây là một số sự kiện.

  1. Các MFC ném một con trỏ đến một trường hợp CMemoryException toàn cầu có tên là "_simpleMemoryException" (xem thêm AfxThrowMemoryException())
  2. nó là một CException mà m_bAutoDelete là sai.

Ý tưởng: Nếu có thể thay đổi thư viện C++ - chỉ tĩnh, bạn có thể chuyển tiếp khai báo class CException; và/hoặc class CMemoryException; vào không gian tên gốc.

Thêm khối catch với catch (CMemoryException* pEx) {...} và/hoặc catch (CException* pEx) {...} tại mỗi địa điểm có khối std::bad_alloc-catch. Kể từ khi con trỏ bị bắt là một con trỏ đến một đối tượng toàn cầu, nó không cần thiết để gọi pEx->Delete();.

Bằng cách này, thư viện C++ - chỉ-tĩnh không bắt buộc phải bao gồm afx.h hoặc/và liên kết với MFC. Tôi đã thử nó trong VC2010, và nó hoạt động tốt. (chỉ khi RTTI được bật, và chỉ khi không ai thay đổi MFC-NewHandler bằng AfxSetNewHandler thành một cái gì đó khác với mặc định-MFC-NewHandler AfxNewHandler)

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