Filter's deconstructor not called and output still active object warning window
Hello, I have wrote a filter to act like the dump filter in the DirectSDK C++ sample. When I open up the GraphEdit.exe and put my filter as a rendering filter in the graph, it works fine. When I then choose to close the GraphEdit.exe application, an warning dialog tells me that ( I have 5 objects left active ). It's been annoying so I tried to figure it out.
In the DllEntryPoint function there is a routine called: DbgDumpObjectRegister(); I use this routine and find out that there are really 5 objects of mine and not deleted in the deconstructor routine. My question is, I have the deconstructor routine but it didn't been called, why? and How do I overcome this?
The dumped debugging message are the following:
=====DbgInitialize()=====
qpMP2Writer.dll(tid e0) 11029 :
qpMP2Writer.dll(tid e0) 11029 : ID Object Description
qpMP2Writer.dll(tid e0) 11029 :
qpMP2Writer.dll(tid e0) 11029 : 83 ( 6eea0) MP2Writer Pass Through
qpMP2Writer.dll(tid e0) 11029 : 5 ( 6eea0) CqpMP2WriterInputPin
qpMP2Writer.dll(tid e0) 11029 : 4 ( 6eea0) CqpMP2WriterInputPin
qpMP2Writer.dll(tid e0) 11029 : 3 ( 6eea0) CqpMP2Writer
qpMP2Writer.dll(tid e0) 11029 : 2 ( 6eea0) CqpWriter
qpMP2Writer.dll(tid e0) 11029 :
qpMP2Writer.dll(tid e0) 11029 : Total object count 5
=====End=====
Thanks
[1357 byte] By [
BrianBin] at [2007-12-24]
Hi, The problem is still un-resolved.
Basically my problem is like another guy posted in : http://www.ureader.com/message/454226.aspx but mine situation is that the deconstructor is not called! I am sure that deconstructor is using "delete" operator to delete objects. But since the system doesn't call my deconstructor, how can my objects be deleted?
I will give some pieces of my code to express my issue more clearly: (Acutally its based on Micrsoft Dump filter)
class CqpMP4Writer : public CBaseFilter, public ISpecifyPropertyPages, public CPersistStream, public IqpMP4Prop
{
public:
CqpMP4Writer( CqpWriter *pWriter, LPUNKNOWN pUnk, CCritSec *pLock, HRESULT *phr );
CBasePin *GetPin( int n );
int GetPinCount();
DECLARE_IUNKNOWN
HRESULT __stdcall NonDelegatingQueryInterface( REFIID riid, void **ppv );
HRESULT __stdcall Run( REFERENCE_TIME tstart );
HRESULT __stdcall Pause();
HRESULT __stdcall Stop();
HRESULT FEvent( long event );
HRESULT ReadFromStream( IStream *pStream );
HRESULT WriteToStream( IStream *pStream );
private:
CqpWriter *m_writer;
BOOL m_bstart;
CCritSec m_csstream;
};
class CqpMP4WriterInputPin : public CRenderedInputPin
{
public:
CqpMP4WriterInputPin( CqpWriter *pWriter, LPUNKNOWN pUnk, CqpMP4Writer *pfilter, CCritSec *plock,
CCritSec *prlock, wchar_t *szname, HRESULT *phr );
HRESULT __stdcall Receive( IMediaSample *pms );
HRESULT __stdcall EndOfStream();
HRESULT __stdcall ReceiveCanBlock();
HRESULT __stdcall NewSegment( REFERENCE_TIME tstart, REFERENCE_TIME tstop, double rate );
HRESULT CheckMediaType( const CMediaType *pmt );
HRESULT BreakConnect();
HRESULT CompleteConnect( IPin *pReceivePin );
void SetWrite( BOOL set );
HRESULT OpenFile();
HRESULT CloseFile();
HRESULT Write( PBYTE pdata, LONG len );
HRESULT HandleWriteFailure();
private:
CqpWriter * const m_writer;
CqpMP4Writer *m_mp4writer;
CCritSec * const m_receivelock;
REFERENCE_TIME m_tlast;
HANDLE m_hfile;
wchar_t m_filename[256];
};
class CqpWriter : public CUnknown, public IFileSinkFilter
{
public:
DECLARE_IUNKNOWN
CqpWriter( LPUNKNOWN pUnk, HRESULT *phr );
virtual ~CqpWriter();
static CUnknown * WINAPI CreateInstance( LPUNKNOWN punk, HRESULT *phr );
HRESULT Write( PBYTE pdata, LONG len );
HRESULT __stdcall SetFileName( LPCOLESTR szfile, const AM_MEDIA_TYPE *pmt );
HRESULT __stdcall GetCurFile( LPOLESTR *szfile, AM_MEDIA_TYPE *pmt );
HRESULT Init();
private:
friend class CqpMP4Writer;
friend class CqpMP4WriterInputPin;
HRESULT __stdcall NonDelegatingQueryInterface( REFIID riid, void **ppv );
HRESULT OpenFile();
HRESULT CloseFile();
HRESULT HandleWriteFailure();
CqpMP4Writer *m_f_writer;
CqpMP4WriterInputPin *m_pin[2];
CqpMP4Encoder *m_encoder;
CCritSec m_lock;
CCritSec m_pinlock;
CCritSec m_receivelock[2];
CCritSec m_csstream;
CPosPassThru *m_pos;
wchar_t m_filename[256];
BOOL m_binit;
BOOL m_bopen;
BOOL m_error;
int m_format;
};
My factor instance is looked like this:
CFactoryTemplate g_Templates[] =
{
{
L"NAME of MY FILTER",
&CLSID_qpMP4Writer,
CqpWriter::CreateInstance,
NULL,
&sudqpMP4Writer
},
{
L"Property Page",
&CLSID_qpMP4PropertyPage,
CqpMP4Property::CreateInstance
}
};
int g_cTemplates = sizeof( g_Templates ) / sizeof( g_Templates[0] );
I do all the construction in CqpWriter class's constructor. But I tried to use OutputDebugString and Visual Studio .NET 2003 to trace the code, both reveal that when I close the application ( GraphEdit.exe ) the deconstructor is not called....Any suggestions or comment is welcome!
Brian
Graphedt is never going to call your destructor.
What it will do is call IUnknown::Release once for every IUnknown::AddRef (creating the object does an implied AddRef). When the refcount hits zero, you are going to call delete on yourself (check out Release() in combase.cpp).
So, if your destructor is not getting called, somehow the refcount never goes to zero. The question then is, who is doing the AddRef without doing the release? It could be graphedt, but I haven't seen any signs of that kind of bug there, which means it is probably somewhere in your code.
There are a variety of ways to track this kind of thing down, but they are all variations on watching the refcount. The baseclasses have some logging built in that may help with this. Check out:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/debugoutputfunctions.asp
Additionally, making a habit of using SmartPointers tends to avoid this kind of problem.
LGS at 2007-8-31 >
