It's unusal to initialize a static variable in a constructor but sometimes it is useful for storing the first instance of a class using...
if( first == null ) first = this;
...or the most recently created instance of a class using...
mostRecent = this;
I tried this in VMD and it works fine when run without the debugger but with the debugger a method call on either variable results in VMD mysteriously crashing with no exception thrown.
Anybody have any ideas why?
Weird debugger behaviour on statics
-
- Posts: 625
- Joined: Mon Nov 15, 2021 9:23 pm
Re: Weird debugger behaviour on statics
This is going to sound strange, but have you thought of running VM's debugger in an external debugger? You might be able to find out where the debugger goes south if you can sandbox the debugger itself.
Reid
Reid
Cyberwerks Heavy Industries -- viewforum.php?f=76
Re: Weird debugger behaviour on statics
I'm not sure I have sufficient time available to learn how to use an external debugger to debug the internal debugger.
I had some vaguely similar problems when debugging my S-Poly code which relies on some tricky low-level stuff and statics, unfortunately I can't remember the details as it was so long ago. All I recall is thinking there might be a bug in the debugger's handling of statics.
After starting this thread I did a little more research and AFAIK there shouldn't be any problem in storing this to a static inside a Java constructor. So it's not like I'm doing anything naughty.
But for now I've changed my code to do the work outside the constructor. It's less elegant but at least it works both inside and outside the debugger.
Re: Weird debugger behaviour on statics
EDITED: My response was technical nonsense, so I thought it best to remove it to avoid confusing anyone else.
I believe this is the order of initialization in Java:
* static variables and static initializers
* instance variables and instance initializers
* constructors
I believe this is the order of initialization in Java:
* static variables and static initializers
* instance variables and instance initializers
* constructors
Last edited by AllanH on Sun Sep 03, 2023 3:02 pm, edited 1 time in total.
Re: Weird debugger behaviour on statics
Thanks for the suggestion Allan. That gave me another line of enquiry. But still no luck.
The key thing is that the code works absolutely fine when not run using the debugger.
Static variables are supposed to be initialised to default values during class initialization, so well before any constructors are called. So when a constructor is called all its static (class) variables and its instance variables should have default values. e.g. null for reference variables. Although of course statics may have changed value after class initialization and before a particular invocation of a constructor (which is kind of the point in the case of the first static variable referencing the first instance created).
The crash doesn't happen in the constructor but later on so even if first was garbage during construction then it should either pass the first == null test and be set to this or end up being null after construction (in the extremely unlikely event that statics aren't initialized until after the first call of a constructor when the debugger is running).
Also the crash still occurs if I do a simple assignment with no test as in mostRecent = this; So even if mostRecent was garbage on construction it should still end up pointing at this (or at least be null).
And this must be valid as it's routinely referenced during construction to disambiguate parameter names from instance variable names (although I am so used to explict disambiguation that I don't normally use this.x = x;).
I explicit test for null in the later call that crashes. And anyway one would expect a null pointer exception if it was null. So somehow first must I guess be pointing at garbage but ONLY when we are running in debug mode.
The key thing is that the code works absolutely fine when not run using the debugger.
Static variables are supposed to be initialised to default values during class initialization, so well before any constructors are called. So when a constructor is called all its static (class) variables and its instance variables should have default values. e.g. null for reference variables. Although of course statics may have changed value after class initialization and before a particular invocation of a constructor (which is kind of the point in the case of the first static variable referencing the first instance created).
The crash doesn't happen in the constructor but later on so even if first was garbage during construction then it should either pass the first == null test and be set to this or end up being null after construction (in the extremely unlikely event that statics aren't initialized until after the first call of a constructor when the debugger is running).
Also the crash still occurs if I do a simple assignment with no test as in mostRecent = this; So even if mostRecent was garbage on construction it should still end up pointing at this (or at least be null).
And this must be valid as it's routinely referenced during construction to disambiguate parameter names from instance variable names (although I am so used to explict disambiguation that I don't normally use this.x = x;).
I explicit test for null in the later call that crashes. And anyway one would expect a null pointer exception if it was null. So somehow first must I guess be pointing at garbage but ONLY when we are running in debug mode.
Re: Weird debugger behaviour on statics
I did some more tests and breakpointing and even though first should be null it isn't when running under the debugger.
I even added an = null to its declaration and a static block that also explicitly sets it to null just to be sure. Yet it isn't null.
So my theory was then that maybe the debugger class initialisation wasn't initialising statics.
So I added some integer test variables.
I found that these were correctly initialized.
Yet first is not null! It appears to be pointing at a valid object but as I've stopped execution with a breakpoint in the constructor BEFORE the first assignment no such object could have been created yet.
It's like another ghost invocation of the constructor is called prior to the debugger waking up, then a second invocation happens. I'm getting a strong sense of déjà vu here. It's the same thing I encountered before.
I'm scratching my head on this one. I've already got a workaround but the thing is really bugging me so I'll investigate a little further tomorrow.
Any ideas welcome.
I even added an = null to its declaration and a static block that also explicitly sets it to null just to be sure. Yet it isn't null.
So my theory was then that maybe the debugger class initialisation wasn't initialising statics.
So I added some integer test variables.
I found that these were correctly initialized.
Yet first is not null! It appears to be pointing at a valid object but as I've stopped execution with a breakpoint in the constructor BEFORE the first assignment no such object could have been created yet.
It's like another ghost invocation of the constructor is called prior to the debugger waking up, then a second invocation happens. I'm getting a strong sense of déjà vu here. It's the same thing I encountered before.
I'm scratching my head on this one. I've already got a workaround but the thing is really bugging me so I'll investigate a little further tomorrow.
Any ideas welcome.
-
- Posts: 625
- Joined: Mon Nov 15, 2021 9:23 pm
Re: Weird debugger behaviour on statics
I was going to try debugging VDM in Visual Studio's debugger, but I updated VS last night, and now it won't run. Sorry.
Reid
Reid
Cyberwerks Heavy Industries -- viewforum.php?f=76
Re: Weird debugger behaviour on statics
Let us know Reid, if you figure out how to use VS to debug VMD.
My suspicion about previous "ghost" invocations of the constructor being called before the debugger wakes up appears to be correct.
I added a static int counter that's incremented right at the end of the connstructor. Then I set a breakpoint before the increment instruction and ran the VMD debugger. If the breakpoint worked correctly then the counter should be 0 but instead it's 3.
The constructor gets called three times during VoltageModule.Initialize() as there are three of the particular objects created. If I comment out one of these instantiations then the counter ends up being 2.
So the breakpoint doesn't trip until AFTER the VMD test client has finished initialization.
What's really mysterious is that even though there are only three objects instantiated (and therefore the constructor only runs three times) the debugger says it has stopped execution inside the constructor PRIOR to incrementing the counter. Yet the counter has been incremented three times.
This is the same impossible situation I encountered a year or two ago when developing S-Poly.
It's like the debugger is capable of time travel. Now I very much doubt that Cherry Audio have accidentally invented a time machine so either there's some massive blunder in my reasoning or the debugger needs debugging.
I guess a possible cause of this behaviour is a thread-safety issue where although the VMD test client should block until the debugger has completed it's own initialization it doesn't and both initializations occur in parallel. Therefore although I'm asking the debugger to breakpoint code that it should be able to intercept, the breakpoint has already been passed multiple times while the debugger is still initializing and when the debugger eventually does wake up it's totally confused by this paradoxical situation.
My suspicion about previous "ghost" invocations of the constructor being called before the debugger wakes up appears to be correct.
I added a static int counter that's incremented right at the end of the connstructor. Then I set a breakpoint before the increment instruction and ran the VMD debugger. If the breakpoint worked correctly then the counter should be 0 but instead it's 3.
The constructor gets called three times during VoltageModule.Initialize() as there are three of the particular objects created. If I comment out one of these instantiations then the counter ends up being 2.
So the breakpoint doesn't trip until AFTER the VMD test client has finished initialization.
What's really mysterious is that even though there are only three objects instantiated (and therefore the constructor only runs three times) the debugger says it has stopped execution inside the constructor PRIOR to incrementing the counter. Yet the counter has been incremented three times.
This is the same impossible situation I encountered a year or two ago when developing S-Poly.
It's like the debugger is capable of time travel. Now I very much doubt that Cherry Audio have accidentally invented a time machine so either there's some massive blunder in my reasoning or the debugger needs debugging.
I guess a possible cause of this behaviour is a thread-safety issue where although the VMD test client should block until the debugger has completed it's own initialization it doesn't and both initializations occur in parallel. Therefore although I'm asking the debugger to breakpoint code that it should be able to intercept, the breakpoint has already been passed multiple times while the debugger is still initializing and when the debugger eventually does wake up it's totally confused by this paradoxical situation.
-
- Posts: 146
- Joined: Sun Jan 22, 2023 5:18 am
- Location: Melbourne
- Contact: