2009-01-14 28 views

Trả lời

9

có thực sự. Cụ thể là bạn thấy các vấn đề với việc gỡ lỗi/phát hành heaps là khác nhau, cũng nếu thư viện của bạn sử dụng vị trí mới, hoặc bất kỳ heap tùy chỉnh bạn sẽ có một vấn đề. Các vấn đề Debug/Release là của xa phổ biến nhất mặc dù.

+0

Yup điều này xảy ra –

+1

Cũng có thể xảy ra khi C++ libs được liên kết tĩnh vào một DLL Windows. – jmucchiello

6

Có, bạn sẽ làm như vậy. Một giải pháp đơn giản là cung cấp chức năng Tạo và Xóa trong thư viện của bạn có thể được gọi từ ứng dụng chính. Hàm Create sẽ thực hiện lệnh mới và trả về một con trỏ, sau đó nó được chuyển vào hàm Xóa để xóa.

16

Điều đó tùy thuộc. Nếu bạn đang nói về một thư viện tĩnh, thì có thể bạn sẽ OK - mã sẽ chạy trong cùng một ngữ cảnh với chương trình chính, sử dụng cùng thư viện thời gian chạy C++. Điều này có nghĩa là newdelete sẽ sử dụng cùng một đống.

Nếu bạn đang nói về một thư viện được chia sẻ (một DLL), thì có thể bạn sẽ không được OK. Mã chạy trong DLL có thể đang sử dụng một thư viện thời gian chạy C++ khác, có nghĩa là bố cục của heap sẽ khác nhau. Các DLL có thể được sử dụng một đống khác nhau hoàn toàn.

Gọi delete (trong chương trình chính) trên con trỏ được phân bổ bởi DLL (hoặc ngược lại) sẽ dẫn đến (tốt nhất) một sự cố ngay lập tức hoặc hỏng hóc bộ nhớ sẽ mất nhiều thời gian để theo dõi .

Bạn có một vài tùy chọn. Đầu tiên là để sử dụng "phương pháp nhà máy" mẫu để tạo và xóa các đối tượng:

Foo *CreateFoo(); 
void DeleteFoo(Foo *p); 

Những nên không được triển khai trong tệp tiêu đề.

Ngoài ra, bạn có thể định nghĩa một phương pháp Destroy trên đối tượng:

class Foo 
{ 
    ~Foo(); 

public: 
    virtual void Destroy(); 
}; 

... một lần nữa, không thực hiện điều này trong file header. Do đó, bạn sẽ triển khai nó:

void Foo::Destroy() 
{ 
    delete this; 
    // don't do anything that accesses this object past this point. 
} 

Lưu ý rằng hàm hủy cho Foo là riêng tư, do đó bạn phải gọi Foo::Destroy.

Microsoft COM thực hiện điều gì đó tương tự, trong đó định nghĩa phương thức Release xóa đối tượng khi số tham chiếu của nó giảm xuống 0.

1

Bạn hoàn toàn đúng là có vấn đề ở đó, nhưng đối với hầu hết các trường hợp, giải pháp thậm chí còn đơn giản hơn các câu trả lời khác (cho đến nay) đã đề xuất. Bạn có thể tiếp tục sử dụng mới và xóa một cách tự do - tất cả những gì bạn cần làm là quá tải mới và xóa cho mỗi lớp trong thư viện của bạn có thể được sử dụng qua các ranh giới DLL.

Cá nhân, tôi chỉ định nghĩa một lớp đơn giản để cung cấp các chức năng cần thiết:

class NewDelete 
{ 
    public: 
     void *operator new (size_t size); 
     void operator delete (void *memory); 
     void *operator new (size_t size, void *ptr); 
     void operator delete (void *memory, void *ptr); 
}; 

Chừng nào những bốn chức năng thành viên đều được định nghĩa trong DLL cùng, sau đó bất kỳ lớp học mà xuất phát từ lớp này là tự động "DLL-an toàn" - mới và xóa có thể được sử dụng bình thường trên chúng mà không đáng lo ngại về ranh giới DLL.

+1

-1. Tôi đã xem xét cùng một loại ý tưởng này, và đã nhận thấy rằng thực hành này là hoàn toàn sai lầm. Tôi không thể (chưa) nói cho xóa nhà điều hành, nhưng nếu nhà điều hành mới không cấp phát bộ nhớ trong không gian DLL một ngoại lệ :: bad_alloc được nêu ra, vì các thư viện chia sẻ hoặc DLL không được thừa nhận bởi Standard C++, hành vi không xác định. Như một ngoại lệ quy tắc chung sẽ không vượt qua thư viện chia sẻ hoặc ranh giới DLL. Có điều này xảy ra để làm việc nếu cả bạn và khách hàng của bạn sử dụng các môi trường phát triển phù hợp, nhưng khoảnh khắc một trong hai thay đổi, mọi thứ sẽ nổ tung trong khuôn mặt khách hàng của bạn. – Geoff

+0

Tôi nên làm rõ trong lưu ý ở trên của tôi: Nó sẽ xảy ra để làm việc với (gần đây) phù hợp với môi trường phát triển của MSVC, không biết về bất kỳ những người khác mặc dù. – Geoff

4

Đó là sự cố mà tôi chỉ thấy trên Windows.

Hệ thống Unix không tạo thói quen buộc thư viện được chia sẻ liên kết với các phiên bản khác nhau của cùng một thư viện trong cùng một chương trình và tất cả các biểu tượng được tải đều hiển thị trên toàn cầu. Điều đó có nghĩa rằng nếu một đối tượng được cấp phát trong một phần của mã và bị xóa trong một mã khác, cả hai đều đang sử dụng cùng một thư viện hệ thống để thực hiện nó.

Tôi phải nói, vấn đề này Windows tạo ra với các DLL runtime C khác nhau của nó thực sự gây phiền nhiễu và không tự nhiên đối với một lập trình viên C. Nhìn vào thư viện C; nó có các chức năng như strdup mà malloc chuỗi và mong đợi các lập trình viên để gọi miễn phí() trên đó. Nhưng làm điều tương tự trong thư viện của riêng bạn trên Windows và chỉ chờ đợi vụ nổ. Bạn sẽ phải chờ đợi, quá, bởi vì nó sẽ không xảy ra trong quá trình phát triển nhưng chỉ sau khi bạn đã đưa ra các DLL biên dịch cho một số sap nghèo khác.

+1

Điều này không liên quan gì đến HĐH, nhưng cách liên kết libc. Tôi đã làm việc tại một cửa hàng Linux nơi chúng tôi đã thực sự liên kết tĩnh với ứng dụng của chúng tôi và nó dẫn đến chính xác cùng một vấn đề. –

+0

Nếu bạn làm strdup và miễn phí trong thư viện của bạn, bạn vẫn ổn. Đó là chỉ khi bạn làm strdup trong một thời gian chạy và miễn phí trong một thời gian khác, sau đó có một vấn đề. Và Zan Lynz là chính xác, điều này xảy ra trên tất cả các nền tảng nếu bạn muốn/cần nhiều thời gian chạy. –

3

Old New Thing đã đề cập đến điều này trước đây. Ông cũng đưa ra một danh sách các giải pháp chính của Microsoft.

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