digitalmars.D.bugs - Garbage collection from associative arrays
- Sebastian Beschke (71/71) Mar 25 2006 The following program creates a couple of instances of a class and
- Sebastian Beschke (3/92) Mar 25 2006 Well, I found a workaround: Just modify the index type of the
- Oskar Linde (9/22) Mar 25 2006 Yeah. The error lies in the AA implementation. The pointers are not stor...
- Sean Kelly (10/20) Mar 25 2006 I ran into something similar to this when first writing Ares, as I was
- Thomas Kuehne (36/107) Mar 26 2006 -----BEGIN PGP SIGNED MESSAGE-----
The following program creates a couple of instances of a class and stores them in an associative array. It then tries to periodically access those instances via the associative array, performing garbage collects in between. As it appears, a fullCollect will destroy the objects, even though they are stored in an associative array. This leads to an access violation in the second loop. Is this a known bug? Can it be fixed? Are there any workarounds? Regards, Sebastian Output on my machine: Loading... class created class created class created 97 98 99 class killed (99) class killed (98) class killed (97) Error: Access Violation Program code: private { import std.gc; import std.stdio; } class SomeClass { this(char value) { writefln("class created"); _value = value; } ~this() { writefln("class killed (%d)", _value); } char value() { return _value; } private { char _value; } } static char[] allChars = [ 'a', 'b', 'c' ]; SomeClass[char] _chars; void _realLoad() { writefln("Loading..."); foreach(char ch; allChars) { _chars[ch] = new SomeClass(ch); } } int main(char[][] args) { bool done = false; _realLoad(); while(!done) { foreach(char ch; allChars) { SomeClass obj = _chars[ch]; writefln("%d", obj.value); } std.gc.fullCollect(); } }
Mar 25 2006
Well, I found a workaround: Just modify the index type of the associative array to int. Sebastian Beschke schrieb:The following program creates a couple of instances of a class and stores them in an associative array. It then tries to periodically access those instances via the associative array, performing garbage collects in between. As it appears, a fullCollect will destroy the objects, even though they are stored in an associative array. This leads to an access violation in the second loop. Is this a known bug? Can it be fixed? Are there any workarounds? Regards, Sebastian Output on my machine: Loading... class created class created class created 97 98 99 class killed (99) class killed (98) class killed (97) Error: Access Violation Program code: private { import std.gc; import std.stdio; } class SomeClass { this(char value) { writefln("class created"); _value = value; } ~this() { writefln("class killed (%d)", _value); } char value() { return _value; } private { char _value; } } static char[] allChars = [ 'a', 'b', 'c' ]; SomeClass[char] _chars; void _realLoad() { writefln("Loading..."); foreach(char ch; allChars) { _chars[ch] = new SomeClass(ch); } } int main(char[][] args) { bool done = false; _realLoad(); while(!done) { foreach(char ch; allChars) { SomeClass obj = _chars[ch]; writefln("%d", obj.value); } std.gc.fullCollect(); } }
Mar 25 2006
Sebastian Beschke wrote:Sebastian Beschke schrieb:Yeah. The error lies in the AA implementation. The pointers are not stored on the correct alignment. Each node of the AA is allocated in the following way: e = cast(aaA *) cast(void*) new byte[aaA.sizeof + keysize + valuesize]; The aaA struct contains two pointers (left&right) and a uint hash. That is 12 bytes on a 32 bit machine. If keysize isn't divisible by 4, the pointers stored as values will not be 4-byte aligned. /OskarThe following program creates a couple of instances of a class and stores them in an associative array. It then tries to periodically access those instances via the associative array, performing garbage collects in between. As it appears, a fullCollect will destroy the objects, even though they are stored in an associative array. This leads to an access violation in the second loop. Is this a known bug? Can it be fixed? Are there any workarounds?Well, I found a workaround: Just modify the index type of the associative array to int.
Mar 25 2006
Sebastian Beschke wrote:The following program creates a couple of instances of a class and stores them in an associative array. It then tries to periodically access those instances via the associative array, performing garbage collects in between. As it appears, a fullCollect will destroy the objects, even though they are stored in an associative array. This leads to an access violation in the second loop. Is this a known bug? Can it be fixed? Are there any workarounds?I ran into something similar to this when first writing Ares, as I was using a map to store thread handles. Basically, when a value is being added to the AA, the AA is first modified to hold some uninitialized data, then memory is allocated, then everything is initialized. As it's possible this is the same problem, you may want to check out my fix here: http://svn.dsource.org/projects/ares/trunk/src/dmdrt/aaA.d Look for "better to fully construct" as a portion of the comment documenting the change. Sean
Mar 25 2006
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Sebastian Beschke schrieb am 2006-03-25:The following program creates a couple of instances of a class and stores them in an associative array. It then tries to periodically access those instances via the associative array, performing garbage collects in between. As it appears, a fullCollect will destroy the objects, even though they are stored in an associative array. This leads to an access violation in the second loop. Is this a known bug? Can it be fixed? Are there any workarounds? Regards, Sebastian Output on my machine: Loading... class created class created class created 97 98 99 class killed (99) class killed (98) class killed (97) Error: Access Violation Program code: private { import std.gc; import std.stdio; } class SomeClass { this(char value) { writefln("class created"); _value = value; } ~this() { writefln("class killed (%d)", _value); } char value() { return _value; } private { char _value; } } static char[] allChars = [ 'a', 'b', 'c' ]; SomeClass[char] _chars; void _realLoad() { writefln("Loading..."); foreach(char ch; allChars) { _chars[ch] = new SomeClass(ch); } } int main(char[][] args) { bool done = false; _realLoad(); while(!done) { foreach(char ch; allChars) { SomeClass obj = _chars[ch]; writefln("%d", obj.value); } std.gc.fullCollect(); } }Added to DStress as http://dstress.kuehne.cn/run/a/associative_array_19_A.d http://dstress.kuehne.cn/run/a/associative_array_19_B.d http://dstress.kuehne.cn/run/a/associative_array_19_C.d http://dstress.kuehne.cn/run/a/associative_array_19_D.d http://dstress.kuehne.cn/run/a/associative_array_19_E.d http://dstress.kuehne.cn/run/a/associative_array_19_F.d http://dstress.kuehne.cn/run/a/associative_array_19_G.d http://dstress.kuehne.cn/run/a/associative_array_19_H.d http://dstress.kuehne.cn/run/a/associative_array_19_I.d http://dstress.kuehne.cn/run/a/associative_array_19_J.d http://dstress.kuehne.cn/run/a/associative_array_19_K.d http://dstress.kuehne.cn/run/a/associative_array_19_L.d http://dstress.kuehne.cn/run/a/associative_array_19_M.d http://dstress.kuehne.cn/run/a/associative_array_19_N.d http://dstress.kuehne.cn/run/a/associative_array_19_O.d http://dstress.kuehne.cn/run/a/associative_array_19_P.d http://dstress.kuehne.cn/run/a/associative_array_19_Q.d http://dstress.kuehne.cn/run/a/associative_array_19_R.d http://dstress.kuehne.cn/run/a/associative_array_19_S.d http://dstress.kuehne.cn/run/a/associative_array_19_T.d http://dstress.kuehne.cn/run/a/associative_array_19_U.d http://dstress.kuehne.cn/run/a/associative_array_19_V.d http://dstress.kuehne.cn/run/a/associative_array_19_W.d http://dstress.kuehne.cn/run/a/associative_array_19_X.d http://dstress.kuehne.cn/run/a/associative_array_19_Y.d http://dstress.kuehne.cn/run/a/associative_array_19_Z.d Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFEJnMW3w+/yD4P9tIRAvB4AJ0avLmBabxpxj3ujexMKtcGYw8BHgCgoQKf o/X2nCdTtYsp7NUYex3yBsI= =zzTM -----END PGP SIGNATURE-----
Mar 26 2006