www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Cycle detected between modules with ctors/dtors

reply Mandeep <mandeep brars.co.in> writes:
Hi,

I am trying to compile the code that was working with dmd 2.050 using 
dmd 2.052.

The code compiles but it gives me errors with message when trying to run:

Cycle detected between modules with ctors/dtors

This was not happening earlier with 2.050. I am not able to produce a 
smaller test case for this but it is happening with a lot of code 
pieces. A few scenarios in which this is happening is if a class passes 
its reference to child class for usage.

I understand that the above might not be a fit datapoint for analysis 
but wanted to understand if this is known or someone else has faced this?


Thanks & Regards
Mandeep
Apr 22 2011
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
 Hi,
 
 I am trying to compile the code that was working with dmd 2.050 using
 dmd 2.052.
 
 The code compiles but it gives me errors with message when trying to run:
 
 Cycle detected between modules with ctors/dtors
 
 This was not happening earlier with 2.050. I am not able to produce a
 smaller test case for this but it is happening with a lot of code
 pieces. A few scenarios in which this is happening is if a class passes
 its reference to child class for usage.
 
 I understand that the above might not be a fit datapoint for analysis
 but wanted to understand if this is known or someone else has faced this?
It happens when a module imports - directly or indirectly - another module which imports it - directly or indirectly - and they both have static constructors and/or static destructors (it _might_ not happen if one of them has static constructors but not static destructors and the other has static destructors and no static constructors, but if they both have either a static constructor or static destructor, it _will_ happen). This is because the compiler cannot determine which order to run the static constructors/destructors in. It doesn't know whether one depends on the other or whether the order matters, so it just doesn't accept it (though you usually get the error at runtime, not when it compiles; I'm not sure how or why you'd get it at compile time). Now, why you weren't seeing the problem with dmd 2.050 but are now with dmd 2.052, I don't know. The solution is generally to either make it so that one of the modules doesn't have any static constructors or destructors or to offload the initialization to another module (such as std.stdio does with std.stdiobase) by having the new module's static constructor call a function in the original module to do the initialization for that module. But if you do that, you then have the responsibility to make sure that there isn't an actual circular dependency in the static constructors themselves, or you're going to run into trouble. You can find discussions on how to solve the problem in the archives - probably on the D newsgroup. - Jonathan M Davis
Apr 23 2011
next sibling parent Mandeep <mandeep brars.co.in> writes:
On 04/23/2011 02:04 PM, Jonathan M Davis wrote:
 Hi,

 I am trying to compile the code that was working with dmd 2.050 using
 dmd 2.052.

 The code compiles but it gives me errors with message when trying to run:

 Cycle detected between modules with ctors/dtors

 This was not happening earlier with 2.050. I am not able to produce a
 smaller test case for this but it is happening with a lot of code
 pieces. A few scenarios in which this is happening is if a class passes
 its reference to child class for usage.

 I understand that the above might not be a fit datapoint for analysis
 but wanted to understand if this is known or someone else has faced this?
It happens when a module imports - directly or indirectly - another module which imports it - directly or indirectly - and they both have static constructors and/or static destructors (it _might_ not happen if one of them has static constructors but not static destructors and the other has static destructors and no static constructors, but if they both have either a static constructor or static destructor, it _will_ happen). This is because the compiler cannot determine which order to run the static constructors/destructors in. It doesn't know whether one depends on the other or whether the order matters, so it just doesn't accept it (though you usually get the error at runtime, not when it compiles; I'm not sure how or why you'd get it at compile time). Now, why you weren't seeing the problem with dmd 2.050 but are now with dmd 2.052, I don't know. The solution is generally to either make it so that one of the modules doesn't have any static constructors or destructors or to offload the initialization to another module (such as std.stdio does with std.stdiobase) by having the new module's static constructor call a function in the original module to do the initialization for that module. But if you do that, you then have the responsibility to make sure that there isn't an actual circular dependency in the static constructors themselves, or you're going to run into trouble. You can find discussions on how to solve the problem in the archives - probably on the D newsgroup. - Jonathan M Davis
Thanks, this worked for me. I shifted the code in the static constructor to another module and it works well now. Regards Mandeep
Apr 23 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 23 Apr 2011 04:34:39 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:


 It happens when a module imports - directly or indirectly - another  
 module
 which imports it - directly or indirectly - and they both have static
 constructors and/or static destructors (it _might_ not happen if one of  
 them
 has static constructors but not static destructors and the other has  
 static
 destructors and no static constructors, but if they both have either a  
 static
 constructor or static destructor, it _will_ happen).
Note, the cyclic detection algorithm does not distinguish between these scenarios. It does distinguish between thread local and shared ctor/dtors, but it just uses a single flag to denote having static constructors or destructors. I think the reason might be that the runtime is supposed to run destructors in reverse order as constructors. If it did the cycle detection independently, you would possibly have a different order for destruction. I'm not sure it really matters. It might be worth a bugzilla report/further discussion. -Steve
Apr 25 2011
prev sibling next sibling parent Heinz <malagana15 yahoo.es> writes:
I haven't faced this myself. DMD is complaining about module Ctors and Dtors, so
the bug must be there. But, i'm very curious about the scenario you mention,
nested classes accessing its outer class:

How are you referring the parent class from the child classes?
Use the "outer" property of the child classes and see if that helps a bit.
Apr 24 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 23 Apr 2011 02:16:22 -0400, Mandeep <mandeep brars.co.in> wrote:

 Hi,

 I am trying to compile the code that was working with dmd 2.050 using  
 dmd 2.052.

 The code compiles but it gives me errors with message when trying to run:

 Cycle detected between modules with ctors/dtors
The cyclic module import code was changed significantly in 2.051, due to this bug: http://d.puremagic.com/issues/show_bug.cgi?id=4384 I would appreciate if you think the cycle is not correct to post a case of where cycle detection is flagging a cycle that shouldn't be considered a cycle. -Steve
Apr 25 2011
parent reply Mandeep <mandeep brars.co.in> writes:
On 04/25/2011 07:56 PM, Steven Schveighoffer wrote:
 On Sat, 23 Apr 2011 02:16:22 -0400, Mandeep <mandeep brars.co.in> wrote:

 Hi,

 I am trying to compile the code that was working with dmd 2.050 using
 dmd 2.052.

 The code compiles but it gives me errors with message when trying to run:

 Cycle detected between modules with ctors/dtors
The cyclic module import code was changed significantly in 2.051, due to this bug: http://d.puremagic.com/issues/show_bug.cgi?id=4384 I would appreciate if you think the cycle is not correct to post a case of where cycle detection is flagging a cycle that shouldn't be considered a cycle. -Steve
The cases i could find were pieces of bigger codebase with cycles coming out of more than 4-5 files with lot of code. I tried to repeat the code sequence with a couple of files with simplistic function but was not able to come out with a smaller test case for the above. Would try to come up with a test case again if i can. But i think moving around the code from static constructors as suggested in an earlier post in the thread helped. Also, I think that the cyclic const/dest have a problem, because the same code was working find with 2.050. Another bit of diff from my older scenario is that 2.050 was on 32 bit and i am using -m64 with 2.052, which i am not sure should be a problem. Regards Mandeep
Apr 25 2011
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 25 Apr 2011 14:07:28 -0400, Mandeep <mandeep brars.co.in> wrote:

 On 04/25/2011 07:56 PM, Steven Schveighoffer wrote:
 On Sat, 23 Apr 2011 02:16:22 -0400, Mandeep <mandeep brars.co.in> wrote:

 Hi,

 I am trying to compile the code that was working with dmd 2.050 using
 dmd 2.052.

 The code compiles but it gives me errors with message when trying to  
 run:

 Cycle detected between modules with ctors/dtors
The cyclic module import code was changed significantly in 2.051, due to this bug: http://d.puremagic.com/issues/show_bug.cgi?id=4384 I would appreciate if you think the cycle is not correct to post a case of where cycle detection is flagging a cycle that shouldn't be considered a cycle. -Steve
The cases i could find were pieces of bigger codebase with cycles coming out of more than 4-5 files with lot of code. I tried to repeat the code sequence with a couple of files with simplistic function but was not able to come out with a smaller test case for the above. Would try to come up with a test case again if i can. But i think moving around the code from static constructors as suggested in an earlier post in the thread helped. Also, I think that the cyclic const/dest have a problem, because the same code was working find with 2.050.
The cyclic check is conservative, there is a very good possibility that the cyclic dependency does not alter the execution of the code at all. So just because the code runs correctly does not mean that there is not a cycle. All the cycle checker does is guarantee that the static constructors/destructors are executed in a sane order. The compiler doesn't give enough info (and can't AFAIK) to tell if the cycle is harmful or not. But if the cycle checker is identifying a cycle where there isn't one, I want to fix that. It should be simple to verify, just follow the path listed in the exception and see if the cycle does exist. If this is an error, you can email me privately, and I can help you reduce the test case.
 Another bit of diff from my older scenario is that 2.050 was on 32 bit  
 and i am using -m64 with 2.052, which i am not sure should be a problem.
Although I have not tested the 64-bit compiler (not having a 64-bit linux box), I believe that the cyclic import check is the same. -Steve
Apr 25 2011