2011-11-18 24 views
47

Trước hết, có ít nhất 4-5 chủ đề có chủ đề tương tự về SO. Tôi đọc từng người trong số họ và tôi không cảm thấy họ thực sự giúp tôi với vấn đề cụ thể này. Nếu ai đó tìm thấy một câu hỏi trùng lặp tôi xin lỗi. Tôi đã thực hiện chia sẻ của tôi tìm kiếm trước khi tôi đăng này, vì nó có vẻ như một câu hỏi rất phổ biến.Cách thay thế đúng nhà khai thác mới và xóa toàn cầu

Tôi đang sử dụng Visual Studio .NET 2003 trên Windows 7.

Tôi có quá tải riêng của tôi về mới/xóa điểm đó để tùy chỉnh của riêng tôi gọi đến malloc() và free() cho chẩn đoán. Quá tải mới/xóa của tôi nằm trong tệp tiêu đề mà tôi đã đưa vào một vài tệp.

Vấn đề là, cơ sở mã là khá nhiều spaghetti và không có cách nào dễ dàng để đảm bảo các quá tải này được mọi thứ sử dụng. Có bao gồm các thư viện của bên thứ ba là hộp đen. Chúng tôi cũng sử dụng STL ở khắp mọi nơi.

Trong các thử nghiệm của tôi, tôi thấy rằng STL vẫn đang trộn các cuộc gọi đến/xóa mới và các cuộc gọi mới/xóa MSVC chuẩn.

Có vẻ như thực tế không bao gồm tệp tiêu đề của tôi trong hàng nghìn tệp khác, quá trình này sẽ mất quá nhiều thời gian. Bất cứ ai có thể cung cấp một số lời khuyên về cách đúng và hiệu quả quá tải mới/xóa trên toàn cầu để mọi thứ sử dụng quản lý bộ nhớ tùy chỉnh của tôi?

+0

Nếu bạn xác định các nhà khai thác trên toàn cầu trong một tiêu đề trước khi biên soạn mà nên bao gồm mặt đất nhất. Cách khác, bạn có thể sử dụng chức năng heap CRT nếu điều này là để phát hiện rò rỉ bộ nhớ. – AJG85

Trả lời

63

Đó không phải là cách tính năng này hoạt động. Bạn thay thế hai toán tử và điều này được thực hiện tại liên kết thời gian. Tất cả những gì bạn cần làm là viết một TU duy nhất mà định nghĩa những toán tử này và liên kết nó với nhau. Không ai khác bao giờ cần phải biết về điều này:

// optional_ops.cpp 

void * operator new(std::size_t n) throw(std::bad_alloc) 
{ 
    //... 
} 
void operator delete(void * p) throw() 
{ 
    //... 
} 

Về nguyên tắc, không có nhu cầu về bất kỳ tập tin tiêu đề để khai báo các chức năng này (operator new, operator delete), kể từ khi tờ khai của hai chức năng đã được hardcoded vào ngôn ngữ, nếu bạn muốn. Tuy nhiên, các tên std, std::bad_allocstd::size_tkhông được đặt trước, vì vậy, bạn có thể muốn bao gồm <new> hoặc một số tiêu đề khác để cung cấp các tên đó.

Trong C++ 11 trở lên, bạn có thể sử dụng cách khác decltype(sizeof(0)) để nhận kích thước tham số đầu tiên theo cách không yêu cầu bất kỳ loại thư viện nào. C++ 11 cũng có một mô hình ngoại lệ đơn giản hơn mà không có các đặc tả ngoại lệ động (cuối cùng được loại bỏ khỏi ngôn ngữ hoàn toàn trong C++ 17).

void * operator new(decltype(sizeof(0)) n) noexcept(false) 
{ 
    //... 
} 
+1

Liệu người liên kết có phàn nàn về các định nghĩa trùng lặp không? Tôi nghĩ rằng ODR áp dụng ở đây. Chưa kể chúng ta có 120 DLL mà chúng ta xây dựng, và tôi phải liên kết nó trong mỗi dự án DLL đó. Tôi đoán điều này vẫn tốt hơn các lựa chọn thay thế. –

+3

@RobertDailey: Không, trường hợp đặc biệt, được bao gồm bởi các tài liệu tham khảo yếu, chuẩn, v.v. Tôi thực sự đã báo cáo lỗi trong GCC liên quan đến ngày hôm trước, vì vậy với phiên bản mới nhất này thậm chí nên làm việc với '-fwhole-program' và '-flto' và whatnot (xem [ở đây] (http://stackoverflow.com/questions/7629270/how-does-stdstring-allocate-memory-in-gcc-with-fwhole-program) và [tại đây] (http : //gcc.gnu.org/bugzilla/show_bug.cgi? id = 50594).) ' –

+0

Bạn có thể giải thích ý của mình bằng cách" được đề cập trong tiêu chuẩn "và" tham chiếu yếu "không? Cảm ơn!! –

31

Ngoài ra thêm những dòng này:

void *operator new[](std::size_t s) throw(std::bad_alloc) 
{ 
    // TODO: implement 
    return NULL; 
} 
void operator delete[](void *p) throw() 
{ 
    // TODO: implement 
} 
Các vấn đề liên quan