none
Why does this code (about Sensors API) lead to high usage of memory ? RRS feed

  • Question

  • Hi all,

    Sorry to disturb you. My code is as followed.

    template <class T> 
    void safeRelease(T **ppT)
    {
        if (*ppT)
        {
    	(*ppT)->Release();
            *ppT = NULL;
        }
    }
    
    int test()
    {	
    	ISensorManager* pSensorManager = NULL;    	
    	ISensorCollection* pSensorColl = NULL;	
    
    	CoCreateInstance(CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pSensorManager));	
    	pSensorManager->GetSensorsByCategory(SAMPLE_SENSOR_CATEGORY_DATE_TIME, &pSensorColl);	
    	pSensorManager->RequestPermissions(0, pSensorColl, TRUE);	
    
    	safeRelease(&pSensorColl);	
    	safeRelease(&pSensorManager);	
    	return 0;
    }
    
    int main()
    {
    	CoInitialize(NULL);
    
    	int cnt = 0;
    	for (int i = 0; i < 10000; i++)	
    		if (test() == 0) cnt++;
    	cout << cnt << endl;
    
    	CoUninitialize();
    }

    Everytime test() is called, the usage of memory will increase a lot. What's worse, this memory is not recycled until the program terminates.

    As a result, when the program finishes the "for (int i = 0; i < 10000; i++)" loop in main(), the memory used by it will increase to larger than 500MB.

    If I delete the code "pSensorManager->RequestPermissions(0, pSensorColl, TRUE)", the usage of memory will be much lower.

    Could you please tell me,  What's the reason of high usage of memory ?

    And, how to reduce the usage of memory when my program needs to call RequestPermissions API ? e.g. How to recycle the memory used by RequestPermissions API ?

    Thank you very much.


    Monday, September 3, 2012 12:28 PM

All replies

  • There is a community addition to call SetEventSink() explicitly since Release() does not free theirs sinks. Have you tried to call SetEventSink() explicitly?

    You'll find this community addition at the bottom of http://msdn.microsoft.com/en-us/library/windows/desktop/dd318867%28v=vs.85%29.aspx



    Phil Ineichen - This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, September 4, 2012 10:58 AM
  • Thanks for your reply.

    I modify my code as you suggest, but it doesn't seem to work.

    The new code is as follow.

    	pSensorManager->GetSensorsByCategory(SAMPLE_SENSOR_CATEGORY_DATE_TIME, &pSensorColl);
    	pSensorManager->RequestPermissions(0, pSensorColl, TRUE);
    
    	pSensorColl->GetCount(&count);
    	for (int i = 0; i < count; i++)
    	{
    		pSensorColl->GetAt(i, &pSensor);
    		pSensor->SetEventSink(NULL);
    		safeRelease(&pSensor);
    	}
    	safeRelease(&pSensorColl);
    	
    	pSensorManager->SetEventSink(NULL);
    	safeRelease(&pSensorManager);	

    Is there anything else to pay attention to ?

    Thank you.


    Tuesday, September 4, 2012 2:53 PM
  • How much memory gets leak? The _CrtMemCheckpoint() and _CrtMemDifference() APIs let you determine how much memory has been leaked. You'll find more information about these APIs here http://msdn.microsoft.com/en-us/library/x98tx3cf.aspx 


    Phil Ineichen - This posting is provided "AS IS" with no warranties, and confers no rights.

    Wednesday, September 5, 2012 10:46 AM
  • Thanks for your reply.

    Actually I have tried _CrtDumpMemoryLeaks before I posted this question on MSDN. But it reported that no memory leak was detected.  That's why I cannot find out why the RequestPermissions API leads to high usage of memory.

    The only thing I can see from the output of debugger is that, after I call the RequestPermissions API, the number of threads will increase a lot.

    PS. I doubt that whether the _CrtDumpMemoryLeaks is useful for COM. I wrote a simple COM program without calling any Release() function, _CrtDumpMemoryLeaks cannot detect any memory leak. Only when I use malloc/new and forget to call free/delete, _CrtDumpMemoryLeaks can detect the memory leak.

    Thank you.



    Wednesday, September 5, 2012 12:21 PM
  • Thanks for your reply.

    I see it from task manager. When the program runs, the memory (private set) used by this program increases rapidly. In addition, in the performance tab of task manager, I can see the memory curve raises quickly.

    If I remove RequestPermissions from my code, the usage of memory is quite low.

    Thank you.

    Wednesday, September 5, 2012 3:11 PM
  • Which Windows version are you targeting?  In Win7 an extra AddRef was called on each sensor in the collection.
    Wednesday, September 5, 2012 9:15 PM
  • Thanks for your reply.

    I am using Windows 7. As you say, in Win7 an extra AddRef was called on each sensor in the collection, so I try to release each sensor. The code is as follow. However, it doen't seem to work.

    pSensorColl->GetCount(&count);
    for (int i = 0; i < count; i++)
    {
    	pSensorColl->GetAt(i, &pSensor);
    	pSensor->SetEventSink(NULL);
    	safeRelease(&pSensor);
    }
    safeRelease(&pSensorColl);
    
     

    Is there anything else I should pay attention to ?

    Thank you.


    Thursday, September 6, 2012 1:40 AM
  • Try the following.  Note that the SetEventSink(NULL) call is a no-op as you didn't set an event sink (and besides the call would only have called Release on your ISensorEvents interface.

    Please be aware that this work around should only be used in Win7.

    int test() { ISensorManager* pSensorManager = NULL; ISensorCollection* pSensorColl = NULL; HRESULT hr = CoCreateInstance(CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pSensorManager)); if (SUCCEEDED(hr)) { hr = pSensorManager->GetSensorsByCategory(SAMPLE_SENSOR_CATEGORY_DATE_TIME, &pSensorColl); if (SUCCEEDED(hr)) { pSensorManager->RequestPermissions(0, pSensorColl, TRUE); // Each sensor will have a ref count of 2 at this point // note that even if the call fails the sensors in the collection // could still be over ref'd so I didn't use return value ULONG count; hr = pSensorColl->GetCount(&count); if (SUCCEEDED(hr)) { for (int i = 0; i < count; i++) { ISensor* pSensor; // GetAt will AddRef the sensor hr = pSensorColl->GetAt(i, &pSensor); if (SUCCEEDED(hr)) { // sensor will have a ref count of 3 at this point                         safeRelease(&pSensor);

                            safeRelease(&pSensor); // sensor will have a ref count of 1 at this point } } } // Releasing the sensor collection calls Release // on each sensor in the collection safeRelease(&pSensorColl); // All sensors should be released by this point } safeRelease(&pSensorManager); } return 0; }




    Thursday, September 6, 2012 6:07 PM
  • Thanks for your reply.

    I modify my code as you suggest. But it doesn't seem to work. The usage of memory is still high.

     if (SUCCEEDED(hr))
    {
        // sensor will have a ref count of 3 at this point
        safeRelease(&pSensor);
        safeRelease(&pSensor);
        // sensor will have a ref count of 1 at this point
    } 

    As you say, sensor will have a ref count of 3 before any safeRelease() is called.

    However, I try to output the return value of pSensor->Release() and I find that, when safeRelease() is called for the first time, the pSensor->Release() which is called in this safeRelease() returns 0. That's to say, sensor has a ref count of 1 (instead of 3) before any safeRelease() is called. Therefore, maybe the problem is not related to the ref count of pSensor ?

    My environment is as follow.
     
    OS: Windows 7 Ultimate
     
    Softwares on OS: Visual Studio 2010 Ultimate, WDK 7.1 (There are no other softwares installed on my Windows)
     
    Sensor Driver: TimeSensor Sample on MSDN (http://msdn.microsoft.com/en-us/library/windows/hardware/ff545893(v=vs.85).aspx)
     
    Sensor Application code: mentioned above
     
    How do I run the sensor code mentioned above:
     
        After the first permission dialog pops up, I choose "deny". With this operation, the permission dialog will never pop up again. This simplifies the test job. Then I run the code mentioned above directly (double clicks on the program and view its memory consumption in task manager).

    I think my windows 7 is rather clean because I only install VS and WDK. Besides, the driver is correct because it is offered by WDK. Therefore, I am very confused at why the code mentioned above will lead to high usage of memory. Do I make any mistake ?
     
    Thank you.






    Friday, September 7, 2012 4:42 PM