Speicherverlust mit CoInitialize und CoCreateInstance



  • Hallo... ich benutzte folgenden Code um mir Zugriff auf die "geplanten Tasks" zu verschaffen

    HRESULT				result;
    
    	/////////////////////////////////////////////////////////////////
    	// Call CoInitialize to initialize the COM library and 
    	// then call CoCreateInstance to get the Task Scheduler object. 
    	/////////////////////////////////////////////////////////////////
    	result = CoInitialize(NULL);
    	if (SUCCEEDED(result))
    	{
    		result = CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void **) &m_ITaskScheduler);
    		if (FAILED(result))
    		{
    			CoUninitialize();
    			m_ITaskScheduler = NULL;
    			m_LastErrorString = "CoCreateInstance with CLSID_CTaskScheduler failed";
    			return;
    		}
    	}
    	else
    	{
    		CoUninitialize();
    		m_ITaskScheduler = NULL;
    		m_LastErrorString = "CoInitialize failed";
    		return;
    	}
    

    Hier passier was

    CoUninitialize();
    	if (m_ITaskScheduler != NULL)
    	{
    		m_ITaskScheduler->Release();
    		m_ITaskScheduler = NULL;
    	}
    

    Den Source habe ich so aus einem Beispiel.
    Nun ist aber das Problem, dass hier Speicher verloren geht. Pro Aufruf ca. 512 Byte.

    Weiß da jemand Rat?



  • CoUninitialize() sollte die letzte Anweisung sein, danach darf kein Zugriff mehr auf COM-Zeiger erfolgen.


  • Mod

    Und wenn schon ein Objekt erzeugt wird, dann muss es auch wieder freigegeben werden. Zudem heißt dies bei Inproc Servern, nicht, dass die DLL sofort entladen wird, selbst wenn das letzte Objekt zerstört wurde.



  • war nur falsch zusammenkopiert...

    con- und destruktur meiner klasse dafür

    YTaskScheduler::YTaskScheduler()
    {
    	HRESULT				result;
    
    	m_LastErrorString = "";
    	m_CurrentTaskName = "";
    	m_ITaskScheduler = NULL;
    	m_ITask = NULL;
    	m_ITaskTrigger = NULL;
    
    	/////////////////////////////////////////////////////////////////
    	// Call CoInitialize to initialize the COM library and 
    	// then call CoCreateInstance to get the Task Scheduler object. 
    	/////////////////////////////////////////////////////////////////
    	result = CoInitialize(NULL);
    	if (SUCCEEDED(result))
    	{
    		result = CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void **) &m_ITaskScheduler);
    		if (FAILED(result))
    		{
    			CoUninitialize();
    			m_ITaskScheduler = NULL;
    			m_LastErrorString = "CoCreateInstance with CLSID_CTaskScheduler failed";
    			return;
    		}
    	}
    	else
    	{
    		CoUninitialize();
    		m_ITaskScheduler = NULL;
    		m_LastErrorString = "CoInitialize failed";
    		return;
    	}
    }
    
    YTaskScheduler::~YTaskScheduler()
    {
    	if (m_ITaskScheduler != NULL)
    	{
    		m_ITaskScheduler->Release();
    		m_ITaskScheduler = NULL;
    	}
    
    	if (m_ITask != NULL)
    	{
    		m_ITask->Release();
    		m_ITask = NULL;
    	}
    
    	if (m_ITaskTrigger != NULL)
    	{
    		m_ITaskTrigger->Release();
    		m_ITaskTrigger = NULL;
    	}
    
    	CoUninitialize();
    }
    

    sieht doch prima aus... oder?

    Stefan



  • Nein, nicht ganz.

    Wenn CoInitialize im Konstruktor fehlschlägt, dann wird CoUninitialize in der Fehlerbehandlung trotzdem aufgerufen. CoUninitialize darf nur aufgerufen werden, wenn ein vorheriges CoInitialize erfolgreich (SUCCEEDED) war. Deshalb muss im Destruktor auch noch eine Prüfung hin. Wenn man die CoInitialize/CoUninitialize-Aufrufe nicht sorgfältig austariert, dann kann es auch passieren, dass man mal eben sein ganzes Programm bei COM abmeldet. Ganz böse wird das, wenn man sowas als Shellerweiterung macht. Dann entzieht man auch der Anwendung, in deren Kontext man läuft, den COM-Boden unter den Füßen weg.

    Das nächste Problem kommt, wenn CoCreateInstance fehlschlägt. In diesem Fall wird CoUninitialize auch zweimal aufgerufen (Konstruktor und Destruktor).



  • Hallo sri,

    ok das hab ich gefixt. Ich hatte das ausprobiert und ein CoUninitialize ohne CoInitialize hatte keine auswirkung. egal so ist ja nun richtig.

    dies hat aber mit dem problem nix zu tun.

    CoInitialize(NULL);
    CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void **) &m_ITaskScheduler);
    m_ITaskScheduler->Release();
    CoUninitialize();
    

    Speicher weg????


Anmelden zum Antworten