Toon posts:

[COM/MSXML] Object te vaak gereleased?

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben bezig met het maken van een client-server applicatie en het leek mij mede met oog op de toekomstige uitbreidbaarheid en het koppelen van client software die door anderen gemaakt is handig om voor de communicatie tussen de client en de server XML te gebruiken. XML genereren gaat prima, XML parsen uit een file gaat ook uitstekend, maar zodra ik zelf een ISequentialInputStream implementeer om te gebruiken als 'voer' voor de XML parser (ik maak gebruik van SAX2) gaan er dingen fout.

Onderstaande code geeft de volgende output:
MYContent
MyReader
MyReaderImpl
AddRef
AddRef
<?xml version="1.0" ?>
<dicomfile>
<header>
<encoding>
</encoding>
<length>
</length>
</header>
</dicomfile>
Release
Release
Release
~MyReaderImpl
~MyReader
~MYContent
Er staan dus 2 AddRefs in de code, en 3 Releases. Nou is mij altijd geleerd dat het aantal AddRef aanroepen gelijk is aan het aantal Release aanroepen.

Weet een van jullie wat ik fout doe? :)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// XMLRead.cpp : Defines the entry point for the console application.

#include "stdafx.h"

#include "MyContent.h"
#include "SAXErrorHandlerImpl.h"

class MyReader : public ISequentialStream
{
public:
    MyReader() { printf("MyReader\n"); };
    virtual ~MyReader() {  printf("~MyReader\n"); };

    long __stdcall QueryInterface(const struct _GUID &,void ** );
    unsigned long __stdcall AddRef(void);
    unsigned long __stdcall Release(void);

    virtual HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG * pcbRead) = 0;
    virtual HRESULT STDMETHODCALLTYPE Write(const void *pv, ULONG cb, ULONG * pcbWritten) = 0;
};

long __stdcall MyReader::QueryInterface(const struct _GUID &riid,void ** ppvObject)
{
    if (__uuidof(ISequentialStream) == riid)
    {
        *ppvObject = (ISequentialStream *)this;
        return S_OK;
    }
    
    return E_NOINTERFACE;
}

unsigned long __stdcall MyReader::AddRef()
{
    printf("AddRef\n");
  
    return 0;
}

unsigned long __stdcall MyReader::Release()
{
    printf("Release\n");
    
    return 0;
}

class MyReaderImpl : public MyReader
{
public:
    MyReaderImpl()
    {
        printf("MyReaderImpl\n"); 
        m_nOffset = 0;

        pData = "<?xml version=\"1.0\" standalone=\"yes\" ?>" \
                "<dicomfile>" \
                "<header>" \
                "  <encoding>base-64</encoding>" \
                "  <length>120</length>" \
                "</header>" \
                "</dicomfile>";

        m_nDataLen = strlen(pData);
    }

    ~MyReaderImpl()
    {
        printf("~MyReaderImpl\n"); 
    }

    HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG *pcbRead)
    {
        int nToDo = cb;

        if ((m_nOffset + nToDo) > m_nDataLen) nToDo = m_nDataLen - m_nOffset;

        memcpy(pv, &pData[m_nOffset], nToDo);
        m_nOffset += nToDo;
        *pcbRead = nToDo;
        
        if (nToDo) return S_OK;
        return S_FALSE;
    };

    HRESULT STDMETHODCALLTYPE Write(const void *pv, ULONG cb, ULONG *pcbWritten)
    {
        return S_OK;
    }

private:
    char *pData; 

    int m_nDataLen;
    int m_nOffset;
};

int main(int argc, char* argv[])
{
    CoInitialize(NULL);

    {
        MyContent pMC;
        MyReaderImpl pMR;

        ISAXXMLReaderPtr pReader = NULL;

        pReader.CreateInstance(CLSID_SAXXMLReader40);

        HRESULT hr = pReader->putContentHandler(&pMC);

        CComVariant Out(&pMR);

        hr = pReader->parse(Out);
    }

    CoUninitialize();
    return 0;
}

PS: Sorry voor het enorm lange bericht :P

Verwijderd

Het is geen Release te veel 't is een AddRef te weinig, je implementatie van QueryInterface is niet helemaal wat het wezen moet, volgens de specs dient QI ook AddRef aan te roepen.
[edit]
Verder vergeet je ook nog IUnknown in je QueryInterface

Verwijderd

Topicstarter
Het is ook mijn aller-aller eerste poging iets met COM te doen, en zoals vaker; alle begin is moeilijk (vind ik wel tenminste :). Heb jij een URL of iets anders waar een goede voorbeeldimplementatie staat van zo'n QueryInterface toevallig?

Verwijderd

Aller begin is moeilijk en vooral met COM. :)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
STDMETHODIMP CMyClass::QueryInterface(REFIID riid , void** ppv)
{
    if (IID_IUnknown ==riid || IID_IMyInterface== riid)
    {
        *ppv=this;
        AddRef();
        return S_OK;
    } 
    else
    {
        *ppv = NULL;
        return E_NOINTERFACE;
    }
}

Sites heb ik niet echt, ik kan je wel "The COM and COM+ programming primer" van alan gordon aanraden. Neemt je stapje voor stapje mee van C++ naar COM/COM+

Verwijderd

*Trap* gaat 't beter nu? of heeft 't nog steeds 'n vrij hoog "vaag" gehalte? :?

Verwijderd

Topicstarter
*Trap* gaat 't beter nu? of heeft 't nog steeds 'n vrij hoog "vaag" gehalte?
Gaat wel goed nu. Begin een beetje door te krijgen waarom dingen gedaan worden zoals ze gedaan worden inmiddels. Mijn XML command parser doet 't uitstekend nu :) (XML reader is inmiddels uitgebouwd om vanaf een TCP socket te lezen enzo)
Pagina: 1