www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Garbage collection from associative arrays

reply Sebastian Beschke <s.beschke gmx.de> writes:
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
next sibling parent reply Sebastian Beschke <s.beschke gmx.de> writes:
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
parent Oskar Linde <olREM OVEnada.kth.se> writes:
Sebastian Beschke wrote:

 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?

Well, I found a workaround: Just modify the index type of the associative array to int.

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. /Oskar
Mar 25 2006
prev sibling next sibling parent Sean Kelly <sean f4.ca> writes:
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
prev sibling parent Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----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