www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Something wrong with GC

reply stunaep <admin pea2nuts.com> writes:
The gc throws invalid memory errors if I use Arrays from 
std.container.
For example, this throws an InvalidMemoryOperationError:
import std.stdio;
import std.container;

void main() {
	new Test();
}

class Test {
	
	private Array!string test = Array!string();
	
	this() {
		test.insert("test");
		writeln(test[0]);
	}
}
and here's the stack trace
	testt.exe!app.onInvalidMemoryOperationError( void* _param_0 ) 
Line 21	D
 	testt.exe!_D2gc2gc2GC134__T9runLockedS57_D2gc2gc2GC11removeRangeMFNbNiPvZ2goFNbNiPS2gc2gc3GcxPvZvS19_D2gc2gc9otherTimelS19_D2gc2gc9numOtherslTPS2gc2gc3GcxTPvZ9runLockedMFNbNi
PS2gc2gc3GcxKPvZv() + 0x52 bytes	D
 	testt.exe!_D2gc2gc2GC11removeRangeMFNbNiPvZv() + 0x29 bytes	D
 	testt.exe!gc_removeRange() + 0x21 bytes	D
 	testt.exe!_D4core6memory2GC11removeRangeFNbNixPvZv() + 0xd 
 bytes	D
 	testt.exe!std.container.array.Array!string.Array.Payload.~this() Line 229 +
0x1f bytes	D
 	testt.exe!object._destructRecurse!(std.container.array.Array!string.Array.Payloa
)._destructRecurse( std.container.array.Array!string.Array.Payload* s ) Line
2409 + 0xd bytes	D
 	testt.exe!object.destroy!(std.container.array.Array!string.Arr
y.Payload).destroy( std.container.array.Array!string.Array.Payload* obj ) Line
2778 + 0xd bytes	D
 	testt.exe!std.typecons.RefCounted!(std.container.array.Array!s
ring.Array.Payload, cast(RefCountedAutoInitialize)0).RefCounted.~this() Line
4864 + 0x10 bytes	D
 	testt.exe!std.container.array.Array!string.Array.~this() Line 
 198 + 0x15 bytes	D
 	testt.exe!app.Test.~this() Line 10 + 0x19 bytes	D
 	testt.exe!rt_finalize2() + 0xb8 bytes	D
 	testt.exe!rt_finalizeFromGC() + 0x24 bytes	D
 	testt.exe!_D2gc2gc3Gcx5sweepMFNbZm() + 0x3a3 bytes	D
 	testt.exe!_D2gc2gc3Gcx11fullcollectMFNbbZm() + 0x57a bytes	D
 	testt.exe!_D2gc2gc2GC86__T9runLockedS56_D2gc2gc2GC18fullCollectNoStackMFNbZ2goFNbPS2gc2gc3GcxZmTPS2gc2gc3GcxZ9runLockedM
NbKPS2gc2gc3GcxZm() + 0x72 bytes	D
 	testt.exe!_D2gc2gc2GC18fullCollectNoStackMFNbZv() + 0x11 
 bytes	D
 	testt.exe!gc_term() + 0x14 bytes	D
 	testt.exe!rt_term() + 0x9e bytes	D
 	testt.exe!_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZv() 
 + 0x4d bytes	D
 	testt.exe!_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv() + 0x6f
bytes	D
 	testt.exe!_d_run_main() + 0x419 bytes	D
 	testt.exe!__entrypoint.main( int argc, char** argv ) + 0x22 
 bytes	D
 	testt.exe!__tmainCRTStartup() Line 255 + 0x12 bytes	D
 	kernel32.dll!0000000076cd59cd	
 	ntdll.dll!0000000076f0b891	
Not sure what to do here
Mar 20 2016
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 20/03/16 8:49 PM, stunaep wrote:
 The gc throws invalid memory errors if I use Arrays from std.container.
 For example, this throws an InvalidMemoryOperationError:
 import std.stdio;
 import std.container;

 void main() {
     new Test();
 }

 class Test {

     private Array!string test = Array!string();

     this() {
         test.insert("test");
         writeln(test[0]);
     }
 }
and here's the stack trace
     testt.exe!app.onInvalidMemoryOperationError( void* _param_0 ) Line
 21    D
     testt.exe!_D2gc2gc2GC134__T9runLockedS57_D2gc2gc2GC11removeRangeMFNbNiPvZ2goFNbNiPS2gc2gc3GcxPvZvS19_D2gc2gc9otherTimelS19_D2gc2gc9numOtherslTPS2gc2gc3GcxTPvZ9runLockedMFNbNiKPS2gc2gc3GcxKPvZv()
 + 0x52 bytes    D
     testt.exe!_D2gc2gc2GC11removeRangeMFNbNiPvZv() + 0x29 bytes    D
     testt.exe!gc_removeRange() + 0x21 bytes    D
     testt.exe!_D4core6memory2GC11removeRangeFNbNixPvZv() + 0xd bytes    D
     testt.exe!std.container.array.Array!string.Array.Payload.~this()
 Line 229 + 0x1f bytes    D
     testt.exe!object._destructRecurse!(std.container.array.Array!string.Array.Payload)._destructRecurse(
 std.container.array.Array!string.Array.Payload* s ) Line 2409 + 0xd
 bytes    D
     testt.exe!object.destroy!(std.container.array.Array!string.Array.Payload).destroy(
 std.container.array.Array!string.Array.Payload* obj ) Line 2778 + 0xd
 bytes    D
     testt.exe!std.typecons.RefCounted!(std.container.array.Array!string.Array.Payload,
 cast(RefCountedAutoInitialize)0).RefCounted.~this() Line 4864 + 0x10
 bytes    D
     testt.exe!std.container.array.Array!string.Array.~this() Line 198
 + 0x15 bytes    D
     testt.exe!app.Test.~this() Line 10 + 0x19 bytes    D
     testt.exe!rt_finalize2() + 0xb8 bytes    D
     testt.exe!rt_finalizeFromGC() + 0x24 bytes    D
     testt.exe!_D2gc2gc3Gcx5sweepMFNbZm() + 0x3a3 bytes    D
     testt.exe!_D2gc2gc3Gcx11fullcollectMFNbbZm() + 0x57a bytes    D
     testt.exe!_D2gc2gc2GC86__T9runLockedS56_D2gc2gc2GC18fullCollectNoStackMFNbZ2goFNbPS2gc2gc3GcxZmTPS2gc2gc3GcxZ9runLockedMFNbKPS2gc2gc3GcxZm()
 + 0x72 bytes    D
     testt.exe!_D2gc2gc2GC18fullCollectNoStackMFNbZv() + 0x11 bytes    D
     testt.exe!gc_term() + 0x14 bytes    D
     testt.exe!rt_term() + 0x9e bytes    D
     testt.exe!_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZv() +
 0x4d bytes    D
     testt.exe!_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv() +
 0x6f bytes    D
     testt.exe!_d_run_main() + 0x419 bytes    D
     testt.exe!__entrypoint.main( int argc, char** argv ) + 0x22
 bytes    D
     testt.exe!__tmainCRTStartup() Line 255 + 0x12 bytes    D
     kernel32.dll!0000000076cd59cd
     ntdll.dll!0000000076f0b891
Not sure what to do here
That looks like an error indeed. But move the initialization of Array into the constructor. --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus
Mar 20 2016
prev sibling next sibling parent reply thedeemon <dlang thedeemon.com> writes:
On Sunday, 20 March 2016 at 07:49:17 UTC, stunaep wrote:
 The gc throws invalid memory errors if I use Arrays from 
 std.container.
Those arrays are for RAII-style deterministic memory release, they shouldn't be freely mixed with GC-allocated things. What happens here is while initializing Array sees it got some GC-ed value type (strings), so it tells GC to look after those strings. When your program ends runtime does a GC cycle, finds your Test object, calls its destructor that calls Array destructor that tries to tell GC not to look at its data anymore. But during a GC cycle it's currently illegal to call such GC methods, so it throws an error. Moral of this story: try not to store "managed" (collected by GC) types in Array and/or try not to have Arrays inside "managed" objects. If Test was a struct instead of a class, it would work fine.
Mar 21 2016
parent reply stunaep <admin pea2nuts.com> writes:
On Monday, 21 March 2016 at 07:55:39 UTC, thedeemon wrote:
 On Sunday, 20 March 2016 at 07:49:17 UTC, stunaep wrote:
 The gc throws invalid memory errors if I use Arrays from 
 std.container.
Those arrays are for RAII-style deterministic memory release, they shouldn't be freely mixed with GC-allocated things. What happens here is while initializing Array sees it got some GC-ed value type (strings), so it tells GC to look after those strings. When your program ends runtime does a GC cycle, finds your Test object, calls its destructor that calls Array destructor that tries to tell GC not to look at its data anymore. But during a GC cycle it's currently illegal to call such GC methods, so it throws an error. Moral of this story: try not to store "managed" (collected by GC) types in Array and/or try not to have Arrays inside "managed" objects. If Test was a struct instead of a class, it would work fine.
So what am I do to? Any other language can do such a thing so trivially... I also run into the same problem with emsi_containers TreeMap. It is imperative that I can store data such as
 public class Example1 {
	
	private File file;
	
	public this(File f) {
		this.file = f;	
	}
 }
or
 public class Example2 {
	
	private int one;
	private int two;
	
	public this(int one, int two) {
		this.one = one;
		this.two = two;
	}
 }
in a tree map and list of some sort. Neither of the above work whether they are classes or structs and it's starting to become quite bothersome...
Mar 22 2016
next sibling parent Edwin van Leeuwen <edder tkwsping.nl> writes:
On Tuesday, 22 March 2016 at 13:46:41 UTC, stunaep wrote:
 public class Example2 {
	
	private int one;
	private int two;
	
	public this(int one, int two) {
		this.one = one;
		this.two = two;
	}
 }
in a tree map and list of some sort. Neither of the above work whether they are classes or structs and it's starting to become quite bothersome...
Is there a particular reason why you don't want to use the standard ranges? public class Example2 { private int one; private int two; public this(int one, int two) { this.one = one; this.two = two; } } void main() { auto myExamplesList = [ new Example2( 6,3 ), new Example2(7,5) ]; // Note that if you do a lot of appending then using Appender is more performant than ~= myExamplesList ~= new Example2(9,1); } For trees there is also redBlackTree
Mar 22 2016
prev sibling parent thedeemon <dlang thedeemon.com> writes:
On Tuesday, 22 March 2016 at 13:46:41 UTC, stunaep wrote:
 So what am I do to?
Just learn more about available containers and their semantics. Maybe you don't need Array!T when there is a simple T[]. If you think you do need Array, then think about memory management: where are you going to allocate the data - in the GC heap or outside it. Depending on your answers there are different approaches. It's all solvable if you pause and think what exactly you're trying to do.
Mar 23 2016
prev sibling next sibling parent tsbockman <thomas.bockman gmail.com> writes:
On Sunday, 20 March 2016 at 07:49:17 UTC, stunaep wrote:
 The gc throws invalid memory errors if I use Arrays from 
 std.container.
 ...
 Not sure what to do here
I don't know what your larger goal is, but maybe std.array.Appender would be a better fit?
Mar 21 2016
prev sibling parent reply ag0aep6g <anonymous example.com> writes:
On 20.03.2016 08:49, stunaep wrote:
 The gc throws invalid memory errors if I use Arrays from std.container.
 For example, this throws an InvalidMemoryOperationError:
 import std.stdio;
 import std.container;

 void main() {
     new Test();
 }

 class Test {

     private Array!string test = Array!string();

     this() {
         test.insert("test");
         writeln(test[0]);
     }
 }
I can reproduce the InvalidMemoryOperationError with git head dmd, but there doesn't seem to be a problem with 2.070. So I'd say this is a regression in the development version. I've filed an issue: https://issues.dlang.org/show_bug.cgi?id=15821 You're probably building dmd/phobos from git, or you're using a nightly, right? Maybe you can go back to 2.070.2 until this is sorted out.
Mar 22 2016
parent ag0aep6g <anonymous example.com> writes:
On 22.03.2016 16:56, ag0aep6g wrote:
 I've filed an issue: https://issues.dlang.org/show_bug.cgi?id=15821
And it's been fixed: https://github.com/D-Programming-Language/druntime/pull/1519 Since the issue was a regression, the fix was made against the stable branch. It's going to be in the next release. But it's not yet in master, which means it's also not going to be in the nightlies for now.
Mar 23 2016