krychu / wfc

Wave Function Collapse library in C, plus a command-line tool

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Memory Leak

NullCGT opened this issue · comments

I was running valgrind on a project that I am using this library in, and I noticed some significant memory leakage. I ended up trying the same thing with the sample program, and noticed leaking memory there as well. I'm still trying to track down the exact issue, but it looks like the memory allocated for the wfc struct is not properly freed when wfc_destroy() is called. This occurs both during contradiction and successful output creation.

Valgrind output:

==19741== HEAP SUMMARY:
==19741==     in use at exit: 13,380 bytes in 446 blocks
==19741==   total heap usage: 649 allocs, 203 frees, 78,916,584 bytes allocated
==19741==
==19741== Searching for pointers to 446 not-freed blocks
==19741== Checked 114,832 bytes
==19741==
==19741== 600 (240 direct, 360 indirect) bytes in 10 blocks are definitely lost in loss record 2 of 7
==19741==    at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19741==    by 0x1365C0: wfc_overlapping (in /home/user/Workspace/wfc/wfc)
==19741==    by 0x10A5DF: main (in /home/user/Workspace/wfc/wfc)
==19741==
==19741== 1,560 (624 direct, 936 indirect) bytes in 26 blocks are definitely lost in loss record 4 of 7
==19741==    at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19741==    by 0x13730B: wfc_overlapping (in /home/user/Workspace/wfc/wfc)
==19741==    by 0x10A5DF: main (in /home/user/Workspace/wfc/wfc)
==19741==
==19741== 3,840 (1,536 direct, 2,304 indirect) bytes in 64 blocks are definitely lost in loss record 5 of 7
==19741==    at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19741==    by 0x1370BF: wfc_overlapping (in /home/user/Workspace/wfc/wfc)
==19741==    by 0x10A5DF: main (in /home/user/Workspace/wfc/wfc)
==19741==
==19741== 7,380 (2,952 direct, 4,428 indirect) bytes in 123 blocks are definitely lost in loss record 7 of 7
==19741==    at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19741==    by 0x13678C: wfc_overlapping (in /home/user/Workspace/wfc/wfc)
==19741==    by 0x10A5DF: main (in /home/user/Workspace/wfc/wfc)
==19741==
==19741== LEAK SUMMARY:
==19741==    definitely lost: 5,352 bytes in 223 blocks
==19741==    indirectly lost: 8,028 bytes in 223 blocks
==19741==      possibly lost: 0 bytes in 0 blocks
==19741==    still reachable: 0 bytes in 0 blocks
==19741==         suppressed: 0 bytes in 0 blocks
==19741==
==19741== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)

A more detailed trace, obtained after compiling the debug version:

==20372== HEAP SUMMARY:
==20372==     in use at exit: 25,860 bytes in 862 blocks
==20372==   total heap usage: 1,103 allocs, 241 frees, 79,382,248 bytes allocated
==20372==
==20372== Searching for pointers to 862 not-freed blocks
==20372== Checked 114,800 bytes
==20372==
==20372== 1,500 (600 direct, 900 indirect) bytes in 25 blocks are definitely lost in loss record 2 of 8
==20372==    at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20372==    by 0x12A232: wfc_img_create (wfc.h:382)
==20372==    by 0x12B243: wfc__create_tile_image (wfc.h:670)
==20372==    by 0x12B395: wfc__add_overlapping_images (wfc.h:697)
==20372==    by 0x12C8C6: wfc__create_tiles_overlapping (wfc.h:1207)
==20372==    by 0x12CB07: wfc_overlapping (wfc.h:1279)
==20372==    by 0x12D595: main (wfctool.c:218)
==20372==
==20372== 3,060 (1,224 direct, 1,836 indirect) bytes in 51 blocks are definitely lost in loss record 4 of 8
==20372==    at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20372==    by 0x12A128: wfc_img_copy (wfc.h:359)
==20372==    by 0x12A6AA: wfc__img_flip_horizontally (wfc.h:479)
==20372==    by 0x12B473: wfc__add_flipped_images (wfc.h:720)
==20372==    by 0x12C8F4: wfc__create_tiles_overlapping (wfc.h:1212)
==20372==    by 0x12CB07: wfc_overlapping (wfc.h:1279)
==20372==    by 0x12D595: main (wfctool.c:218)
==20372==
==20372== 7,680 (3,072 direct, 4,608 indirect) bytes in 128 blocks are definitely lost in loss record 6 of 8
==20372==    at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20372==    by 0x12A232: wfc_img_create (wfc.h:382)
==20372==    by 0x12AA5D: wfc__img_rotate90 (wfc.h:529)
==20372==    by 0x12B588: wfc__add_rotated_images (wfc.h:746)
==20372==    by 0x12C945: wfc__create_tiles_overlapping (wfc.h:1224)
==20372==    by 0x12CB07: wfc_overlapping (wfc.h:1279)
==20372==    by 0x12D595: main (wfctool.c:218)
==20372==
==20372== 13,620 (5,448 direct, 8,172 indirect) bytes in 227 blocks are definitely lost in loss record 8 of 8
==20372==    at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20372==    by 0x12A232: wfc_img_create (wfc.h:382)
==20372==    by 0x12AA39: wfc__img_rotate90 (wfc.h:527)
==20372==    by 0x12B588: wfc__add_rotated_images (wfc.h:746)
==20372==    by 0x12C945: wfc__create_tiles_overlapping (wfc.h:1224)
==20372==    by 0x12CB07: wfc_overlapping (wfc.h:1279)
==20372==    by 0x12D595: main (wfctool.c:218)
==20372==
==20372== LEAK SUMMARY:
==20372==    definitely lost: 10,344 bytes in 431 blocks
==20372==    indirectly lost: 15,516 bytes in 431 blocks
==20372==      possibly lost: 0 bytes in 0 blocks
==20372==    still reachable: 0 bytes in 0 blocks
==20372==         suppressed: 0 bytes in 0 blocks
==20372==
==20372== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)

Thanks for filing the issue, this is a great finding. I'll be looking into it asap. Are these traces obtained after a single wfc_run or multiple runs?

I do dev on a mac m1 so it might be challenging to use valgrind.

Thank you for the fast response! This library is a fantastic resource, and I've been really enjoying working with it.

These stacktraces come from a single wfc_run(), and occur both with and without contradictions. Based on the second stacktrace and what I saw when I looked into the codebase, it seems like the issue has to do with the creation of rotated and flipped images, which could mean that images created by wfc_image_copy() are not being properly freed?

I've just merged a fix: #20. After all rotations and flips are done, there is a step which discards duplicate tiles. These duplicates were not freed properly. Your hints and report were very useful in tracking this down. Thanks a lot!

I've made a couple of runs with different configurations and input images and am not seeing more leaks. Let me know if this looks good on your end.

Thanks again, and great to see the library being useful! Feel free to share where / how you use the lib. It's very rewarding :)