Listbox Memory Leak

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Listbox Memory Leak

      Hi,

      I noticed something about listbox. When you delete a listbox or an item of it, not all the memory it was using is released.
      For example,
      -if i create a listbox without any item, my window use 460 bytes
      -if i create a listbox with 1000 items, my window use 41248 bytes
      -now if i delete the 1000 items that i just created, my window use 8264 bytes 8|
      I don't know if it's a normal behavior or there is a problem ? but i think after deleting all the items, my window should go back to only using 460 bytes.
      With code below you can reproduce the problem i faced.
      #include "GUI.h"
      #include "DIALOG.h"

      #define ID_WINDOW_0 (GUI_ID_USER + 0x00)
      #define ID_LISTBOX_0 (GUI_ID_USER + 0x01)
      /*********************************************************************
      *
      * Static data
      *
      **********************************************************************
      */
      /*********************************************************************
      *
      * _aDialogCreate
      */
      static const GUI_WIDGET_CREATE_INFO _aHistoricDialogCreate[] = {
      { WINDOW_CreateIndirect, "Window", ID_WINDOW_0, 0, 0, 240, 274 },
      { LISTBOX_CreateIndirect, 0, ID_LISTBOX_0, 5, 35, 235, 192, 0, 100 },
      };

      /*********************************************************************
      *
      * _cbDialog
      */
      static void _cbDialog(WM_MESSAGE * pMsg) {
      WM_HWIN hItem;

      switch (pMsg->MsgId) {
      case WM_INIT_DIALOG:

      hItem = WM_GetDialogItem(pMsg->hWin, ID_LISTBOX_0);

      for (int i = 0; i < 1000; ++i) {
      LISTBOX_AddString(hItem, "25");
      }

      break;
      case WM_KEY:
      switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) {
      case GUI_KEY_ENTER:
      GUI_EndDialog(pMsg->hWinSrc, 0);
      //WM_DeleteWindow(pMsg->hWin); //even with DeletWindow function, i get the same result
      break;
      default:
      break;
      }
      break;
      default:
      WM_DefaultProc(pMsg);
      break;
      }
      }


      /*********************************************************************
      *
      * Public code
      *
      **********************************************************************
      */
      /*********************************************************************
      *
      * MainTask
      */
      void MainTask(void) {
      GUI_Init();
      GUI_Clear();
      GUI_CreateDialogBox(_aHistoricDialogCreate, GUI_COUNTOF(_aHistoricDialogCreate), _cbDialog, WM_HBKWIN, 0, 24);

      while (1) {
      GUI_Delay(100);
      };
      }

      /*************************** End of file ****************************/
      You'll find also attached a screenshot from emWinSpy when you can see clearly when a listbox is deleted not all the memory it was using is freed.
      Images
      • MemoryLeakListBox.PNG

        11.92 kB, 1,919×349, viewed 364 times
    • Hi,

      This is the normal behavior. Each time a string gets added emWin allocates some memory in form of a block. After deleting the window with the LISTBOX the memory gets freed but the information about the blocks will remain. When the window gets recreated the information structure will get reused.

      At some point it might happen that emWin is not able to allocate any further block even though it has enough memory. Than emWin will will realloc the unused blocks and you will notice that the number of blocks might decrease again.

      I have modified your code. Just set a breakpoint at the second GUI_Delay() in MainTask() and observe NumBytesDelta. It will not increase any further than ~8k.

      You will see that NumBytesDelta will stay at about 8k bytes and NumBlockDelta at 1k blocks.

      C Source Code

      1. #include "GUI.h"
      2. #include "DIALOG.h"
      3. #define ID_WINDOW_0 (GUI_ID_USER + 0x00)
      4. #define ID_LISTBOX_0 (GUI_ID_USER + 0x01)
      5. /*********************************************************************
      6. *
      7. * Static data
      8. *
      9. **********************************************************************
      10. */
      11. /*********************************************************************
      12. *
      13. * _aDialogCreate
      14. */
      15. static const GUI_WIDGET_CREATE_INFO _aHistoricDialogCreate[] = {
      16. { WINDOW_CreateIndirect, "Window", ID_WINDOW_0, 0, 0, 240, 274 },
      17. { LISTBOX_CreateIndirect, 0, ID_LISTBOX_0, 5, 35, 235, 192, 0, 100 },
      18. };
      19. /*********************************************************************
      20. *
      21. * _cbDialog
      22. */
      23. static void _cbDialog(WM_MESSAGE * pMsg) {
      24. WM_HWIN hItem;
      25. int i;
      26. switch (pMsg->MsgId) {
      27. case WM_INIT_DIALOG:
      28. hItem = WM_GetDialogItem(pMsg->hWin, ID_LISTBOX_0);
      29. for (i = 0; i < 1000; ++i) {
      30. LISTBOX_AddString(hItem, "25");
      31. }
      32. break;
      33. case WM_KEY:
      34. switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) {
      35. case GUI_KEY_ENTER:
      36. WM_DeleteWindow(pMsg->hWin); //even with DeletWindow function, i get the same result
      37. break;
      38. }
      39. break;
      40. default:
      41. WM_DefaultProc(pMsg);
      42. break;
      43. }
      44. }
      45. /*********************************************************************
      46. *
      47. * Public code
      48. *
      49. **********************************************************************
      50. */
      51. /*********************************************************************
      52. *
      53. * MainTask
      54. */
      55. void MainTask(void) {
      56. WM_HWIN hDialog;
      57. int NumBytesBefore;
      58. int NumBytesAfter;
      59. int NumBytesDelta;
      60. int NumBlocksBefore;
      61. int NumBlocksAfter;
      62. int NumBlocksDelta;
      63. int Once;
      64. GUI_Init();
      65. GUI_Clear();
      66. NumBytesBefore = GUI_ALLOC_GetNumFreeBytes();
      67. NumBlocksBefore = GUI_ALLOC_GetNumFreeBlocks();
      68. hDialog = GUI_CreateDialogBox(_aHistoricDialogCreate, GUI_COUNTOF(_aHistoricDialogCreate), _cbDialog, WM_HBKWIN, 0, 24);
      69. Once = 0;
      70. while (1) {
      71. GUI_Delay(100);
      72. if (!WM_IsWindow(hDialog) && (Once == 0)) {
      73. Once = 1;
      74. NumBytesAfter = GUI_ALLOC_GetNumFreeBytes();
      75. NumBytesDelta = NumBytesBefore - NumBytesAfter;
      76. NumBlocksAfter = GUI_ALLOC_GetNumFreeBlocks();
      77. NumBlocksDelta = NumBlocksAfter - NumBlocksBefore;
      78. //
      79. // Set breakpoint here and you will notice that NumBytesDelta will not increase
      80. //
      81. GUI_Delay(100);
      82. hDialog = GUI_CreateDialogBox(_aHistoricDialogCreate, GUI_COUNTOF(_aHistoricDialogCreate), _cbDialog, WM_HBKWIN, 0, 24);
      83. Once = 0;
      84. }
      85. }
      86. }
      87. /*************************** End of file ****************************/
      Display All


      Regards
      Sven
      Please read the forum rules before posting.

      Keep in mind, this is *not* a support forum.
      Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
      Should you be entitled to support you can contact us via our support system: segger.com/ticket/

      Or you can contact us via e-mail.