2010-02-22 27 views
5

Tôi hiện đang nghiên cứu COM và mã sau nhầm lẫn với tôi.Làm thế nào một phương pháp thành viên có thể xóa đối tượng?

STDMETHODIMP _(ULONG) ComCar::Release() 
{ 
    if(--m_refCount==0) 
    delete this; // how could this "suicide" deletion be possible? 
    return m_refCount; 
} 

Tôi tự hỏi làm cách nào để xóa đối tượng đối tượng trong phương pháp thành viên? Vì vậy, tôi đã thực hiện thí nghiệm sau:

class A 
{ 
public: 
    void Suicide(void); 
    void Echo(void); 
    char name; 
}; 

void A::Echo(void) 
{ 
    ::printf("echo = %c\n",name); 
} 

void A::Suicide(void) 
{ 
    delete this; 
} 

int main(void) 
{ 
    A a; 
    a.name='a'; 
    a.Suicide(); //failed 
} 

Và việc thực hiện không thành công tại a.Suicide(). Gỡ lỗi báo cáo một số "Debug Assertion Failed". Ai đó có thể làm sáng tỏ tôi không? Nguyên nhân tôi hoàn toàn là một newbie trên COM.

Một chủ đề liên quan là ở đây: Question about COM Release() method

Trả lời

10

Thay đổi cơ thể chính của bạn để:

A* a = new A(); 
a->name='a'; 
a->Sucide(); 

Bạn chỉ có thể xóa những gì được xây dựng bởi new, tất nhiên - nó làm cho không có sự khác biệt nếu đó xóa là trong một chức năng thành viên hoặc ở nơi khác.

7

Trong ví dụ của bạn, Suicide() không thành công vì nó đang gọi xóa trên đối tượng chưa được cấp động, không hợp lệ cho dù chức năng gọi có phải là thành viên hay không.

Các hàm thành viên có thể deletethis - nếu họ biết con trỏ this đã được cấp phát động (thông qua new). Tuy nhiên, họ không thể truy cập các thành viên sau thời điểm đó, nói rất đúng ví dụ bạn đưa ra:

STDMETHODIMP _(ULONG) ComCar::Release() 
{ 
    if(--m_refCount==0) 
    delete this; // how could this "sucide" deletion be possible? 
    return m_refCount; 
} 

kết quả trong hành vi undefined tại báo cáo kết quả return.

+3

Và sửa chữa đơn giản chỉ trả về 0, tất nhiên. – GManNickG

+0

Cảm ơn, Michael, kể từ khi bạn đề cập đến "alloacation động", tôi đoán nếu có một số "alloacation tĩnh" đối diện? nó là gì và sự khác biệt là gì? có thể khó giải thích nó trong một từ. Bạn có thể cho tôi một số tài liệu tham khảo để nghiên cứu sâu hơn không? cảm ơn nhiều. : D – smwikipedia

+1

@GMan: Chỉ muốn làm rõ ý bạn là: 'if (--m_refCount == 0) {xóa cái này; trả về 0; } trả về m_refCount; '. Bạn không thể thay đổi câu lệnh return thành 'return 0;'. – Dan

1

Sử dụng new để phân bổ đối tượng mới của lớp mà bạn sắp hủy bằng cách gọi delete.

2

Bạn không thể xóa đối tượng không được phân bổ động. Các đối tượng COM được phân bổ động.

này hoạt động:

#include <stdio.h> 

class A 
{ 
public: 
    void Sucide(void); 
    void Echo(void); 
    char name; 
}; 

void A::Echo(void) 
{ 
    ::printf("echo = %c\n",name); 
} 

void A::Sucide(void) 
{ 
    delete this; 
} 

void main(void) 
{ 
    A *a = new A; 
    a->name='a'; 
    a->Sucide(); // works 
} 
3

delete this chỉ có hiệu lực khi đối tượng được phân bổ sử dụng các nhà điều hành mới. Đối với tính toán tham chiếu COM, điều này không phải là bất thường.

Tuy nhiên, có một cảnh báo khác: truy cập các biến thành viên sau delete this là không xác định, vì bộ nhớ cho đối tượng đã được trả về cửa hàng miễn phí. Mẫu mã đầu tiên bạn đã đăng thực hiện việc này. Để khắc phục sự cố, hãy sử dụng biến cục bộ:

STDMETHODIMP_(ULONG) ComCar::Release() 
{ 
    ULONG refCount = --m_refCount; 
    if(refCount==0) 
    delete this; 
    return refCount; 
} 
+1

Cá nhân tôi thấy nó hơi lộn xộn hơn, với biến cục bộ. Nếu bạn biết số 0 trong câu lệnh if, chỉ cần trả về 0. – GManNickG

+2

@GMan, nhưng sau đó bạn cần hai câu lệnh trả về, một bên trong 'if' và phương thức bên ngoài - bk1e sẽ lưu lại sự trùng lặp đó! –

+0

Thay vì sao chép câu lệnh trả về, chúng tôi nhân đôi giá trị \ * nhún vai * Có lẽ cái này sạch hơn. – GManNickG

1

Có một lý do đơn giản cho việc này. mới và xóa phải khớp.

Vì vậy, nếu bạn tạo một đối tượng trong một dll và xử lý nó vào một phần khác (exe, dll) C thời gian chạy có thể khác nhau. Trong trường hợp này, bạn không thể gọi xóa vì thời gian chạy không có kiến ​​thức về con trỏ bạn muốn xóa. Nó có thể sụp đổ.

Vì đây là thiết kế tốt để tích hợp phương pháp tự sát. Trong Com của nó một cặp phương pháp.

AddRef 
Release 

có nghĩa là con trỏ có bộ đếm để nhớ số lượng chủ sở hữu mà đối tượng có. Chỉ khi chủ sở hữu cuối cùng gọi xóa đối tượng thực sự bị xóa.

Nhưng tôi nghĩ rằng có lỗi trong quá trình triển khai bạn đã đăng.

return m_refCount; 

không thể thực hiện được khi đối tượng bị xóa. Ít nhất hành vi là không xác định. Tôi nghĩ rằng bạn cần phải lưu trữ m_refCount trên một biến địa phương để trả lại nó trong trường hợp xóa.

STDMETHODIMP _(ULONG) ComCar::Release() 
{ 
    if(--m_refCount==0) { 
    delete this; // how could this "sucide" deletion be possible? 
    return 0; 
    } 
    return m_refCount; 
} 
Các vấn đề liên quan