2017-06-06 131 views
0

我通過USB中斷傳輸使用libUSB同步發現了內存泄漏讀取數據。我的簡單用戶程序本身並未使用任何動態內存分配。內部libusb過度使用動態內存分配。通信流程按預期工作。使用libusb_interrupt_transfer後是否有一個特殊的功能來釋放內部動態內存?有沒有人有一個想法是什麼導致運行時內存不斷增加?內存泄漏同步讀取通過libUSB傳輸數據的中斷

enter image description here

我的協議實現雙向握手。因此,簡單的數據交換會導致OUT(請求),IN(Ack/Nack),IN(響應)和OUT(Ack/Nack)傳輸。報告大小爲32字節,outEndpointAddr爲1,inEndpointAddr爲129,這裏是相關的代碼片段。

int main (void) 
{ 
    uint32_t devFound = 0; 
    uint32_t devErrors = 0; 

    ... 

    int libUsbErr = 0; 
    if(!findSensor(&devFound, &devErrors, &libUsbErr, foundCB)) 
     printf("finding sensor failed %d\n", libUsbErr); 

    if(!openSensor(mySensor, &libUsbErr)) 
     printf("open sensor failed %d\n", libUsbErr); 

    int i = 0; 
    while(1) 
    { 
     printf("[%06d] Int Temp %f C\n",i++, readIntTemper()); 
     Delay(0.5); 
    } 
    closeSensor(&mySensor, NULL); 

    closeSensorContext(); 
    return 0; 
} 

float readIntTemper() 
{ 
    static uint8_t tmp[32]; 
    static uint8_t response[32]; 

    ...//Prepare request frame 

    int libUsbErr = 0; 
    if(!HID_Write(mySensor, tmp, &written, 4000, &libUsbErr)) 
    { 
     printf("write request failed %d\n", libUsbErr); 
     return 0; 
    } 

    //Read Ack/Nack 
    if(!HID_Read(mySensor, tmp, &read, 4000, &libUsbErr)) 
    { 
     printf("Read ACK NACK failed %d\n", libUsbErr); 
     return 0; 
    } 

    ...//Test if Ack/Nack 


    if(!HID_Read(mySensor, response, &read, 4000, &libUsbErr)) 
    { 
     printf("Read response failed %d\n", libUsbErr); 
     return 0; 
    }    

    ... //Prepare ACK 

    if(!HID_Write(mySensor, tmp, &written, 4000, &libUsbErr)) 
    { 
     printf("Ack response failed %d\n", libUsbErr); 
     return 0; 
    } 

    ... 

    float* temper = (float*)&response[8]; 
    return *temper; 
} 

bool HID_Write(const Sensor* sens, uint8_t* repBuf, int* transferred, uint32_t timeout, int* libUsbErr) 
{ 
    if(sens == NULL || repBuf == NULL || transferred == NULL) 
     return returnlibUSBErr(libUsbErr, -1008); ///TODO nice error codes; 

    if(!sens->claimed) 
     return returnlibUSBErr(libUsbErr, -1012); ///TODO nice error codes; 

    int r = libusb_interrupt_transfer(sens->devHandle, sens->outEndpointAddr, 
          repBuf, sens->outRepSize, transferred, timeout); 
    if (r < 0) 
     return returnlibUSBErr(libUsbErr, r); 
    return returnlibUSBErr(libUsbErr, LIB_USB_OK); 
} 

bool HID_Read(const Sensor* sens, uint8_t* repBuf, int* read, uint32_t timeout, int* libUsbErr)    
{  
    if(sens == NULL || read == NULL) 
     return returnlibUSBErr(libUsbErr, -1008); ///TODO nice error codes; 

    if(!sens->claimed) 
     return returnlibUSBErr(libUsbErr, -1012); ///TODO nice error codes;  

    int r = libusb_interrupt_transfer(sens->devHandle, sens->inEndpointAddr, repBuf,sens->inRepSize, read, timeout); 
    if (r < 0) 
     return returnlibUSBErr(libUsbErr, r); 
    return returnlibUSBErr(libUsbErr, LIB_USB_OK); 
} 

編輯

如果遵循這個指令來監視內存的使用情況:

https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/using-performance-monitor-to-find-a-user-mode-memory-leak

要找到泄漏我用UMDH的Windows工具,如這裏提到:

https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/using-umdh-to-find-a-user-mode-memory-leak

問題是我必須使用CVI NI編譯器來構建我的應用程序。我無法從這個編譯器中得到符號表。所以我的堆轉儲差異只顯示地址。

// Each log entry has the following syntax:         
//                   
// + BYTES_DELTA (NEW_BYTES - OLD_BYTES) NEW_COUNT allocs BackTrace TRACEID 
// + COUNT_DELTA (NEW_COUNT - OLD_COUNT) BackTrace TRACEID allocations  
//  ... stack trace ...             
//                   
// where:                 
//                   
//  BYTES_DELTA - increase in bytes between before and after log   
//  NEW_BYTES - bytes in after log          
//  OLD_BYTES - bytes in before log          
//  COUNT_DELTA - increase in allocations between before and after log 
//  NEW_COUNT - number of allocations in after log      
//  OLD_COUNT - number of allocations in before log      
//  TRACEID - decimal index of the stack trace in the trace database  
//   (can be used to search for allocation instances in the original 
//   UMDH logs).              
//                   


+ 80000 (80000 -  0)  1 allocs BackTrace4920B3C 
+  1 ( 1 -  0) BackTrace4920B3C allocations 

    ntdll!RtlAllocateHeap+274 
    cvirte!LoadExternalModule+291EC 
    cvirte!CVIDynamicMemoryInfo+12B6 
    cvirte!CVIDynamicMemoryInfo+1528 
    cvirte!CVIDynamicMemoryInfo+1AF9 
    cvirte!mblen+84D 
    cvirte!_CVI_Resource_Acquire+116 
    cvirte!malloc+68 
    libUSB_HID!???+0 : 41DCE8 
    libUSB_HID!???+0 : 4E95C7 
    libUSB_HID!???+0 : 4C13BE 
    libUSB_HID!???+0 : 4BA09D 
    libUSB_HID!???+0 : 4C7ABA 
    libUSB_HID!???+0 : 4F92F0 
    libUSB_HID!???+0 : 4FB3BD 
    libUSB_HID!???+0 : 4FC50E 
    libUSB_HID!???+0 : 415C31 
    libUSB_HID!???+0 : 408847 
    libUSB_HID!???+0 : 402967 
    libUSB_HID!???+0 : 41B51E 
    libUSB_HID!???+0 : 41A021 
    kernel32!BaseThreadInitThunk+E 
    ntdll!__RtlUserThreadStart+70 

我也換成內的libusb全部免費,分配,釋放calloc和realloc CMDS我一個自己的實現跟蹤每一個內存請求。此跟蹤不顯示任何內存泄漏。如預期的那樣,分配的字節量在運行時保持不變。無論如何,UMDH工具顯示堆分配差異。所以我完全不知道要測試下一個atm。

+1

它是C還是C++?刪除不當標籤。 – tilz0R

+0

你的問題是什麼?你能讀[mcve]和[問]嗎? – Stargateur

+0

我刪除了不適當的標籤。問題:在使用libusb_interrupt_transfer之後是否有一個特殊的功能來釋放任何內部動態內存?有沒有人有一個想法是什麼導致運行時內存不斷增加? –

回答

0

對不起,我把我的程序移植到minGW gcc和everythink正在按預期工作。它接吻我的移植libusb CVI編譯器不完全正確。現在我使用標準的DLL並且內存泄漏消失了。

1

我的簡單用戶程序沒有使用任何動態內存分配。

不幸的是,那些libusb_xxx_transfer函數在內部使用malloc()來做東西。但是它也可以在退出給調用者之前做相應的free()

該內存通常不會返回到操作系統,但會保留在應用程序中以用於下一個調用malloc()。因此,您將在任務管理器中看到一些內存使用情況。

這就是爲什麼你需要更好的工具來檢測實際的內存泄漏,就像valgrind一樣。