digitalmars.D.bugs - [Issue 16824] New: std.experimental.allocator.dispose leaks memory
- via Digitalmars-d-bugs (86/86) Nov 28 2016 https://issues.dlang.org/show_bug.cgi?id=16824
https://issues.dlang.org/show_bug.cgi?id=16824 Issue ID: 16824 Summary: std.experimental.allocator.dispose leaks memory for arrays of more than 1 dimension Product: D Version: D2 Hardware: x86_64 OS: Windows Status: NEW Severity: normal Priority: P1 Component: phobos Assignee: nobody puremagic.com Reporter: atila.neves gmail.com The program below throws an AssertError due to memory leaks when calling dispose with a 2D array. dispose works fine with a 1D array. The issue is there for all N-D arrays where N > 1 (it's easy to get a 3D one with string[][]). A simple fix is to check in the dispose for arrays whether or not the elements are also arrays and recurse. The output for the program: + Allocated ptr 544880 of 16 bytes length + Allocated ptr 544640 of 24 bytes length + Allocated ptr 544EA0 of 24 bytes length - Deallocate ptr 544880 of 16 bytes length core.exception.AssertError allocator.d(42): Memory leak in TestAllocator. Allocations: [ByteRange(544640, 24), ByteRange(544EA0, 24)] ---------------- 0x0040A501 in _d_assert_msg 0x00402388 in _Dmain at C:\Users\Atila\coding\d\experiments\allocator.d(55) 0x0040B337 in D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv 0x0040B2FB in void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() 0x0040B1FC in _d_run_main 0x00409F28 in main at C:\Users\Atila\coding\d\experiments\allocator.d(7) 0x0042804D in mainCRTStartup 0x75C838F4 in BaseThreadInitThunk 0x76F75DE3 in RtlUnicodeStringToInteger 0x76F75DAE in RtlUnicodeStringToInteger The program: import std.stdio; struct TestAllocator { import std.experimental.allocator.common: platformAlignment; import std.experimental.allocator.mallocator: Mallocator; alias allocator = Mallocator.instance; private static struct ByteRange { void* ptr; size_t length; } private ByteRange[] _allocations; enum uint alignment = platformAlignment; void[] allocate(size_t numBytes) { auto ret = allocator.allocate(numBytes); writeln("+ Allocated ptr ", ret.ptr, " of ", ret.length, " bytes length"); _allocations ~= ByteRange(ret.ptr, ret.length); return ret; } bool deallocate(void[] bytes) { import std.algorithm: remove, canFind; import std.conv: text; writeln("- Deallocate ptr ", bytes.ptr, " of ", bytes.length, " bytes length"); bool pred(ByteRange other) { return other.ptr == bytes.ptr && other.length == bytes.length; } assert(_allocations.canFind!pred, text("Unknown deallocate byte range. Ptr: ", bytes.ptr, " length: ", bytes.length, " allocations: ", _allocations)); _allocations = _allocations.remove!pred; return allocator.deallocate(bytes); } ~this() { import std.conv: text; assert(!_allocations.length, text("Memory leak in TestAllocator. Allocations: ", _allocations)); } } void main() { import std.experimental.allocator: dispose, makeArray; TestAllocator allocator; auto ints2d = allocator.makeArray!(int[])(2); foreach(ref ints1d; ints2d) ints1d = allocator.makeArray!(int)(3); allocator.dispose(ints2d); } --
Nov 28 2016