2009-02-24 31 views
19

Tôi đang tạo bộ tìm kiếm rò rỉ bộ nhớ trong chương trình của mình, nhưng cách quá tải mới và xóa (cũng mới [] và xóa []) dường như không làm gì cả.quá tải mới/xóa

void* operator new (unsigned int size, const char* filename, int line) 
{ 
    void* ptr = new void[size]; 
    memleakfinder.AddTrack(ptr,size,filename,line); 
    return ptr; 
} 

Cách tôi quá tải new được hiển thị trong đoạn mã ở trên. Tôi đoán đó là một cái gì đó với các nhà điều hành trở về void * nhưng tôi không biết phải làm gì về nó.

+6

"dường như không làm gì cả": ý của bạn là gì? Bạn đã quá tải toán tử, nhưng bạn chưa * ghi đè * toán tử mặc định mới, vì vậy "new x" gọi mặc định mới trong khi "new (filename, line) x" gọi phiên bản quá tải của bạn. –

Trả lời

11
void* ptr = new void[size]; 

Không thể làm điều đó. Sửa nó.

Không bao giờ cố gắng quá tải mới/xóa toàn cầu. Hoặc có chúng trong một lớp cơ sở và lấy được tất cả các đối tượng của bạn từ lớp này hoặc sử dụng một không gian tên hoặc một tham số cấp phát mẫu. Tại sao, bạn có thể hỏi. Bởi vì trong trường hợp chương trình của bạn có nhiều hơn một tệp và sử dụng STL hoặc các thư viện khác, bạn sẽ định hướng.

Dưới đây là một phiên bản cất của new điều hành từ VS2005 new.cpp:

void * operator new(size_t size) _THROW1(_STD bad_alloc) 
{  // try to allocate size bytes 
    void *p; 
    while ((p = malloc(size)) == 0) 
    if (_callnewh(size) == 0) 
    {  // report no memory 
     static const std::bad_alloc nomem; 
     _RAISE(nomem); 
    } 

    return (p); 
} 
+3

Thực ra, tôi đã có một lý do chính đáng để làm điều đó một lần.Chúng tôi đã có một trình biên dịch "vấn đề", nơi nó đã được sử dụng đống trong một cách không an toàn trên các ràng buộc DLL. Bản sửa lỗi là tạo phiên bản tùy chỉnh "mới" đã sử dụng một tên miền cụ thể. –

+0

Tại sao bạn không nộp lỗi và thay vào đó chọn chơi với lửa? – dirkgently

+0

Chúng tôi đã làm. Câu trả lời chúng tôi nhận được là một cái gì đó dọc theo dòng "DLLs không làm việc rất tốt cross-process trong hệ thống của chúng tôi". Cuối cùng, chúng tôi bỏ việc sử dụng chúng, nhưng trong ngắn hạn, điều này đã khắc phục được sự cố. –

4

Bạn có gọi đúng toán tử đã quá tải, tức là, chuyển nó qua các tham số bổ sung?

4

vấn đề này dựa với hai đối số mà bạn đã thêm vào các nhà điều hành mới quá tải. Hãy thử làm cho tên tập tin và dòng toàn cầu theo một cách nào đó (hoặc biến thành viên nếu bạn đang quá tải mới và xóa cho một lớp duy nhất). Điều đó sẽ hoạt động tốt hơn.

12

Tôi nghĩ rằng vấn đề ở đây là hồ sơ thông số mới của bạn không khớp với thông tin của toán tử chuẩn mới, do đó người dùng không bị ẩn (và do đó vẫn đang được sử dụng).

Tham số cấu hình của bạn cho mới và xóa cần phải trông như thế này:

void* operator new(size_t); 
void operator delete(void*, size_t); 
44

lẽ bạn có thể làm những gì bạn muốn với một chút tiền xử lý ma thuật:

#include <iostream> 

using namespace std; 

void* operator new (size_t size, const char* filename, int line) { 
    void* ptr = new char[size]; 
    cout << "size = " << size << " filename = " << filename << " line = " << line << endl; 
    return ptr; 
} 

#define new new(__FILE__, __LINE__) 

int main() { 
    int* x = new int; 
} 
+12

Điều này thật tuyệt vời. –

+2

phải là 'size_t' thay vì' unsigned int'? Tôi tin rằng trên một số nền tảng các loại này không tương đương. – iggy

+0

Tại sao toán tử 'void * mới (kích thước size_t, const char * filename, int) đối số thứ nhất của' là 'size_t'? Nếu tôi muốn ghi đè lên toán tử 'delete', tôi nên viết gì? – naive231

121

RE:

Không bao giờ cố gắng quá tải mới/xóa toàn cầu

Tại sao nó bất cứ khi nào ai đó cố gắng sử dụng một tính năng ít phổ biến hơn của C++, ai đó hành động như nó sẽ không bao giờ được thực hiện?

Nó được thực hiện tất cả các thời gian, nó là khá phổ biến, và tôi đã không làm việc cho công ty mà không làm điều này.

toàn cầu quá tải mới và xóa cực kỳ hữu ích trong việc theo dõi bộ nhớ, lỗi bộ nhớ, vượt đệm vv

Không ai đầu óc bình thường sẽ phải trải qua một chương trình với vài triệu dòng mã, và thêm một thành viên mới và xóa cho mỗi lớp học. Điều đó thật ngu ngốc.

+1

Điều cần thiết ở đây là ghi đè * mới/xóa thay vì * quá tải *. Tôi đã phải làm điều này gần đây (và lý do tôi đi qua câu hỏi này) trên một hệ thống nhúng bằng cách sử dụng một RTOS. Mặc dù RTOS cung cấp trình bao bọc an toàn cho thread/miễn phí, ứng dụng đã được viết bằng C++ với mới/delete. Để bắt buộc sử dụng malloc/delete an toàn thread, nó là cần thiết để ghi đè lên mới/xóa toàn cầu. Tuy nhiên mới [], xóa [] và mới (std :: nothrow) và xóa (std :: nothrow) cũng cần phải được xem xét. – Clifford

+0

Sự thật là tốt hơn nhiều là trừu tượng mới và xóa đi bằng một macro. MỚI(), DELETE(). Điều này sẽ alow bạn để làm nhiệm vụ bổ sung như kéo một khung stack, Đăng nhập một tập tin và dòng #, Phân bổ từ một đống được xác định trước và vị trí mới nó vào tồn tại. Quá tải chỉ không có đầy đủ các tính linh hoạt mà có thể đạt được thông qua một sự trừu tượng đầy đủ. – Dan

+1

Ngoài ra, viết hệ điều hành của riêng bạn là một ứng dụng tốt. – imallett