[Issue 16824] New: std.experimental.allocator.dispose leaks memory for arrays of more than 1 dimension
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Mon Nov 28 13:53:54 PST 2016
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 at puremagic.com
Reporter: atila.neves at 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 at 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);
}
--
More information about the Digitalmars-d-bugs
mailing list