Memory Leak with BUTTON_SetText() and WM_SetCallback()

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

    • Memory Leak with BUTTON_SetText() and WM_SetCallback()

      I have been running an application using EMWin for a while. A client discovered that some of the screen elements began disappearing after running for around 2 months. I have isolated this to what appears to be a memory leak in EmWin. I am periodically monitoring the used memory in emwin and printing it out.

      I have observed a few things.
      1) removing

      C Source Code

      1. WM_SetCallback(checkbox, button_callback);
      eliminates the memory leak.
      2) removing

      Source Code

      1. BUTTON_SetText(checkbox, "this is a test");


      also eliminates the memory leak.

      Any thoughts on this would be appreciated. I have attached a good portion of a test main that I have been using. I did not include all of it as it is specific to the custom hardware I am using.

      The behavior is as follows:

      • A button is created with the text "this is a test" with a green background.
      • Wait 1 second.
      • The button is deleted.
      • Wait 1 second.
      • Repeat.


      The memory usage is periodically printed. When either 1) or 2) above are done, the memory usage stabilizes. When they are both present, the memory slowly grows. After a point it grows so large that the elements no longer get drawn on the screen.

      I am using emwin v5.32.

      C Source Code

      1. static void window_callback(WM_MESSAGE* pMsg)
      2. {
      3. WM_DefaultProc(pMsg);
      4. }
      5. static void button_callback(WM_MESSAGE* pMsg)
      6. {
      7. BUTTON_Callback(pMsg);
      8. }
      9. static GUI_HWIN _hWnd = 0;
      10. static BUTTON_Handle checkbox;
      11. bool window_created = false;
      12. void CreateWindow()
      13. {
      14. _hWnd = WM_CreateWindow(0, 0, 100, 100, WM_CF_MEMDEV|WM_CF_SHOW, window_callback, NULL);
      15. checkbox = BUTTON_CreateEx(0, 0, 100, 100, _hWnd, WM_CF_MEMDEV|WM_CF_SHOW, 0, widget_id++);
      16. WM_SetCallback(checkbox, button_callback);
      17. BUTTON_SetText(checkbox, "this is a test");
      18. window_created = true;
      19. }
      20. void DestroyWindow()
      21. {
      22. BUTTON_SetText(checkbox, NULL);
      23. WM_SetCallback(checkbox, NULL);
      24. WM_DeleteWindow(_hWnd);
      25. window_created = false;
      26. }
      27. int main()
      28. {
      29. // init system
      30. // init external ram
      31. // init lcd
      32. // init touch
      33. // init emwin
      34. // init timers
      35. while(1)
      36. {
      37. if(print_timer.read_ms() > 100)
      38. {
      39. printf("%ld\r\n", GUI_ALLOC_GetNumUsedBytes());
      40. print_timer.reset();
      41. }
      42. if(change_timer.read_ms() > 1000)
      43. {
      44. if(window_created)
      45. {
      46. DestroyWindow();
      47. }
      48. else
      49. {
      50. CreateWindow();
      51. }
      52. change_timer.reset();
      53. }
      54. // Get touch input
      55. GUI_TOUCH_StoreStateEx(&_touchState);
      56. WM_Exec();
      57. wait_ms(10);
      58. }
      59. }
      Display All

      Thanks for the help,
      Eddie

      The post was edited 2 times, last by eddie.hunckler ().

    • Yes, I can confirm that WM_DeleteWindow(_hWnd); gets called for each created button. Is there anything additional that needs to be done to de-allocate the string? I only observe this leak when both the BUTTON_SetText(checkbox,"test") and WM_SetCallback(checkbox, callback) are called. Either can be called individually without a leak.
    • Hi,

      sorry for the late response. There are a few flaws in your code.

      First, it is necessary to call GUI_Init() in your main task to initialize emWin.

      Then, it doesn't really make sense to set a callback that only calls the default callback. But this won't lead to a crash of your application.

      To delete the parent window with all child windows, you just need to call WM_DeleteWindow(_hWnd). All of the child windows are deleted automatically, as well as text buffers etc. With your code, the windows cannot get deleted, since you set the function pointer to the callback to NULL, by calling WM_SetCallback(NULL) and then you delete the parent. Therefore, please do not set callback pointers to NULL. Setting the pointer to the text of the button is also not necessary.

      I hope this helps you to solve your problem.

      Best regards,

      Florian
    • Hi Florian,

      Thank you for the input here.

      The above example is somewhat contrived. I have more code in the actual application that does things like setting up LCD and calling GUI_Init().

      The actual application callback handles things like touch, painting, focus, and sizing the windows. Here I was just trying to have a minimum setup that causes the leak. I will try and remove the WM_SetCallback(NULL).

      In the meantime, I have worked around the leak by adjusting the button class that I have wrapping these function calls to build a text box on top of a button if text needs to be set there. That way I don't encounter the situation where I used both the callback and the text (either separately used did not seem to cause a leak).

      I had previously identified a memory leak (at least I suspected I did) when using bitmaps on buttons. Prior to destroying a button, I call BUTTON_SetBitmap(_hWnd, idx, NULL); to clear out the bitmap. This seems to eliminate a leak that was happening when using bitmaps on buttons. Perhaps this is related? Do you know if this is common practice for deleting a btimap. It seemed like it was necessary after reading this in the emwin documentation:

      UM03001, V5.22, page 438 wrote:

      Additional information
      If only a bitmap for the unpressed state is set the button will show it also when it is
      pressed or disabled. To deactivate a previously set bitmap, NULL has to be passed as
      pBitmap.
      Thanks for the help,
      Eddie
    • Hi,

      setting the bitmap pointer of a button to NULL is only required if the bitmap should not be shown in the button anymore. So it should be done when its appearance should change, but it isn't a necessary step when deleting a button. As I said, WM_DeleteWindow() should suffice.

      It could very well be that there were memory leaks in the past versions that have been fixed by now. V5.22 is almost seven years old, so you should consider updating to the latest version V6.10h.

      Best regards,

      Florian