yglukhov / nimx

GUI library
MIT License
1.1k stars 75 forks source link

Valgrind issues #442

Closed kb2ma closed 4 years ago

kb2ma commented 4 years ago

I have found significant memory issues when running Valgrind on a minimal nimx application. Details below, and I'd appreciate any insights. Am I missing something?

Environment

Application

nimx_mem.nim

import nimx / [ segmented_control, window ]

proc startApplication() =
  let wnd = newWindow(newRect(40, 40, 800, 600))
  wnd.title = "Mem Test"
*[
  let sc = SegmentedControl.new(newRect(10, 10, 160, 22))
  sc.segments = @["Client", "Server"]
  sc.autoresizingMask = { afFlexibleWidth, afFlexibleMaxY }
  wnd.addSubview(sc)
]*
runApplication:
  startApplication()

Build and Run

   $ nim c --threads:on nimx_mem.nim
   $ valgrind --leak-check=yes --show-leak-kinds=definite ./nimx_mem

After the app starts, I just close it without interacting with it.

Results, without SegmentedControl

==28923== HEAP SUMMARY:
==28923==     in use at exit: 2,957,743 bytes in 9,923 blocks
==28923==   total heap usage: 31,065 allocs, 21,142 frees, 8,874,866 bytes allocated
==28923== 
==28923== 32 bytes in 1 blocks are definitely lost in loss record 543 of 2,706
==28923==    at 0x483B7F3: malloc (vg_replace_malloc.c:309)
==28923==    by 0x544A3CF: XextAddDisplay (in /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0)
==28923==    by 0x77A8674: ???
==28923==    by 0x77AB06C: ???
==28923==    by 0x779ACE1: ???
==28923==    by 0x7796653: ???
==28923==    by 0x7797098: ???
==28923==    by 0x513823A: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28923==    by 0x5138507: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28923==    by 0x510A739: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28923==    by 0x510C977: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28923==    by 0x510D112: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28923== 
==28923== 32 bytes in 1 blocks are definitely lost in loss record 544 of 2,706
==28923==    at 0x483B7F3: malloc (vg_replace_malloc.c:309)
==28923==    by 0x544A3CF: XextAddDisplay (in /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0)
==28923==    by 0x77AC714: ???
==28923==    by 0x77AC5DA: ???
==28923==    by 0x779ACEE: ???
==28923==    by 0x7796653: ???
==28923==    by 0x7797098: ???
==28923==    by 0x513823A: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28923==    by 0x5138507: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28923==    by 0x510A739: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28923==    by 0x510C977: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28923==    by 0x510D112: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28923== 
==28923== LEAK SUMMARY:
==28923==    definitely lost: 64 bytes in 2 blocks
==28923==    indirectly lost: 0 bytes in 0 blocks
==28923==      possibly lost: 1,906,599 bytes in 6,480 blocks
==28923==    still reachable: 1,051,080 bytes in 3,441 blocks
==28923==         suppressed: 0 bytes in 0 blocks
==28923== Reachable blocks (those to which a pointer was found) are not shown.
==28923== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==28923== 
==28923== For lists of detected and suppressed errors, rerun with: -s
==28923== ERROR SUMMARY: 2387 errors from 1269 contexts (suppressed: 2 from 2)

Results, with SegmentedControl

Removed the comments from the code. This run shows significantly more problems with only the addition of the segmented control.

==28975== HEAP SUMMARY:
==28975==     in use at exit: 3,557,358 bytes in 18,866 blocks
==28975==   total heap usage: 88,284 allocs, 69,418 frees, 22,490,084 bytes allocated
==28975== 
==28975== 32 bytes in 1 blocks are definitely lost in loss record 632 of 3,207
==28975==    at 0x483B7F3: malloc (vg_replace_malloc.c:309)
==28975==    by 0x544A3CF: XextAddDisplay (in /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0)
==28975==    by 0x77A8674: ???
==28975==    by 0x77AB06C: ???
==28975==    by 0x779ACE1: ???
==28975==    by 0x7796653: ???
==28975==    by 0x7797098: ???
==28975==    by 0x513823A: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28975==    by 0x5138507: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28975==    by 0x510A739: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28975==    by 0x510C977: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28975==    by 0x510D112: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28975== 
==28975== 32 bytes in 1 blocks are definitely lost in loss record 633 of 3,207
==28975==    at 0x483B7F3: malloc (vg_replace_malloc.c:309)
==28975==    by 0x544A3CF: XextAddDisplay (in /usr/lib/x86_64-linux-gnu/libXext.so.6.4.0)
==28975==    by 0x77AC714: ???
==28975==    by 0x77AC5DA: ???
==28975==    by 0x779ACEE: ???
==28975==    by 0x7796653: ???
==28975==    by 0x7797098: ???
==28975==    by 0x513823A: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28975==    by 0x5138507: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28975==    by 0x510A739: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28975==    by 0x510C977: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28975==    by 0x510D112: ??? (in /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0.10.0)
==28975== 
==28975== 8,807 (6,656 direct, 2,151 indirect) bytes in 26 blocks are definitely lost in loss record 3,167 of 3,207
==28975==    at 0x483B7F3: malloc (vg_replace_malloc.c:309)
==28975==    by 0x105202F4: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==28975==    by 0x105209B8: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==28975==    by 0x10521FDC: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==28975==    by 0x1052906C: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==28975==    by 0x784F9D9: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.6.11)
==28975==    by 0x78506AF: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.6.11)
==28975==    by 0x784DB82: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.6.11)
==28975==    by 0x784F04D: ??? (in /lib/x86_64-linux-gnu/libexpat.so.1.6.11)
==28975==    by 0x7852DBF: XML_ParseBuffer (in /lib/x86_64-linux-gnu/libexpat.so.1.6.11)
==28975==    by 0x10526F42: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==28975==    by 0x1052737B: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==28975== 
==28975== LEAK SUMMARY:
==28975==    definitely lost: 6,720 bytes in 28 blocks
==28975==    indirectly lost: 2,151 bytes in 101 blocks
==28975==      possibly lost: 2,262,479 bytes in 7,977 blocks
==28975==    still reachable: 1,286,008 bytes in 10,760 blocks
==28975==         suppressed: 0 bytes in 0 blocks
==28975== Reachable blocks (those to which a pointer was found) are not shown.
==28975== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==28975== 
==28975== Use --track-origins=yes to see where uninitialised values come from
==28975== For lists of detected and suppressed errors, rerun with: -s
==28975== ERROR SUMMARY: 56147 errors from 2060 contexts (suppressed: 2 from 2)
yglukhov commented 4 years ago

Sorry, I'm not a heavy valgrind user, can't make a good use of its output. It seems however that the leaks are coming from SDL, X, and fontconfig (which is loaded lazily when fonts are rendered. In your case SegmentedControl triggered it). I would assume those are one-shot globals and nothing to worry about. Unless you can prove that the leaks are growing over runtime.

kb2ma commented 4 years ago

OK, thanks. I am not a Valgrind expert either. I am just digging in to a project with nimx, and will monitor memory use over time.

In my project, I use a SegmentedControl to switch the current view. I'd like to confirm that the approach in main.nim shown below is the idiomatic way to do it, and that I can expect GC to clean up any resources for the replaced view.

    let nv = View(newObjectOfClass(allSamples[firstSelectedRow].className))
    nv.init(currentView.frame)
    nv.resizingMask = "wh"
    splitView.replaceSubview(currentView, nv)
    currentView = nv
yglukhov commented 4 years ago

I'd like to confirm that the approach...

Regarding the GC there's nothing to worry about. However I would suggest using the new layout syntax rather than procedural view creation. Samples: https://github.com/yglukhov/nimx/blob/master/test/sample14_layout.nim https://github.com/yglukhov/nimx/blob/version-2/test/main.nim

Docs: https://github.com/yglukhov/nimx/blob/version-2/doc/layout-dsl.md

kb2ma commented 4 years ago

Thanks for the links. I'm just starting to think about layouts.

I'll close for now and monitor memory use.