I get 'Variable x inaccessible here due to optimization'
Asked Answered
B

3

12

I get 'Variable ForAllUsers inaccessible here due to optimization' even if the build configuration is set to 'Debug' and the Optimization is False. So, I cannot debug my program.

Why do I get this?
Which build is ran when I press the Run button?
How can I see


procedure Test(ForAllUsers: boolean);
VAR
   FName, Path1, Path2: string;
   RootKey: HKEY;
begin
 Result:= FALSE;
 TRY
  if ForAllUsers
  then
    begin
     RootKey:= HKEY_CLASSES_ROOT;
     Path1:= '';
     Path2:= '';
    end
  else
    begin
     RootKey:= HKEY_CURRENT_USER;           <----- Break point here
     Path1:= '\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\';
     Path2:= '\Software\Classes\';    
    end;

... end;


Update:
Only minutes since I posted this question, and it was already voted twice up and starred two times. Seems this is a pretty common issue.

Billbug answered 6/6, 2011 at 19:24 Comment(10)
Show the code that you are getting the issue on and I'll help.Vareck
This is normal (and a bit annoying). You simply have to check the variables at some other time (and not at an end 'statement', for instance).Casillas
Hi Andreas. I know that issue from D7. It was annoying but not that much actually. But it is not that. I am in the middle of my procedure.Billbug
I would say it's such kind of the built-in debugger optimization. I know only that you are trying to watch the last (or the only one) occurence of your local variable what debugger takes as optimized so you can't get the value from it. I know only workaround - I use this variable once again and catch it before the last use in the method.Stockist
@Altar - you might be in the middle but it's the last time you use this variable in your procedure. It's driving me crazy too.Stockist
@daemon_x - But my compiler is not set to optimize the code. Optimization if FALSE. In D7 false meant false = do not optimize/alter code.Billbug
@Altar - I know; it looks for me like a long time issue because I have D2009 and it do the same (including Optimization = FALSE).Stockist
@Altar, I'm not sure it's a bug. What assembly code is Delphi generating for that routine with optimization off?Galloglass
@Altar All software has bugs and whenever you upgrade to a new version it takes time to become acclimatised. I for one have been happy with my move from D6 to D2010 which included a relatively simple port of around 1 million LOC.Munificent
@David - Yah... I think I just need a while to get accustomed with this new version. After working with D7 for some years, I got to know it better and get accustomed with the issues it had.Billbug
M
13

We all suffer from this from time to time. What I sometimes do is add some spurious code at the point at which I need to debug the variable that references the variable but does nothing. For example:

if x>0 then x := x*1;

Or if it is a boolean then:

if b then b := not not b;

Something along these lines is usually enough to get the compiler to write out code that keeps the variable alive so that the debugger can inspect it. Make sure you put the code right at the bottom of the routine! And make sure that you remember to remove it before checking the code in.

Munificent answered 6/6, 2011 at 19:36 Comment(6)
+1 for the if b then b := not not b; :) And of course you're right. Anyway it's enough to read the value; you don't need to assign it.Stockist
Hi David. This ever happen to you under Delphi 7? I haven't seen it until now (unless the execution point was indeed at the end of the routine)Billbug
@daemon_x I can never be sure how much you need to do to persuade the compiler to behave as I desire. I tend to err on the safe side!Munificent
@Altar I've never used Delphi 7. I went straight from 6 to 2010.Munificent
@David, nice workaround but I don't believe this is the answer, and I don't believe XE has this bug. Delphi 2010 doesn't AFAICT.Galloglass
@Galloglass I posted this before there was code. It's kind of difficult to know exactly what's going on since we don't know the precise compiler settings that Altar is using.Munificent
G
9

Let's see the difference with and without optimization in code:

procedure test;
var
  x,y,z: integer;
begin
  x:= 1;   //x is stored in register EAX.
  Inc(x);  
  y:= x;   //this is a no-op because it's just a rename.
//After this point x is no longer used.
//Here you will get `Variable x inaccessible here due to optimization`
  z:= 0;   //z is never used 
  if (y = 1) then Inc(z);  //because Delphi knows this code will never execute
end;

Here's the assembly code with optimization:

Project5.dpr.12: x:= 1;   //x is stored in register EAX.
004085E8 B801000000       mov eax,$00000001
Project5.dpr.13: Inc(x);  
004085ED 40               inc eax
Project5.dpr.18: if (y = 1) then Inc(z);
004085EE 48               dec eax  //test to see if eax=1, triggers `jz` if true.
                                   //Delphi put it in to facilitate the `if`, but
                                   //is not smart enough to eliminate it :-)
Project5.dpr.19: end;
004085EF C3               ret 

And here's the code without optimization:

Project5.dpr.11: begin    //note that Delphi doesn't use registers, but the stack 
                          //to keep variables.
004085E8 55               push ebp
004085E9 8BEC             mov ebp,esp      //init the stack frame.
004085EB 83C4F4           add esp,-$0c
Project5.dpr.12: x:= 1;   //x is stored near the top of the stack.
004085EE C745FC01000000   mov [ebp-$04],$00000001
Project5.dpr.13: Inc(x);  
004085F5 FF45FC           inc dword ptr [ebp-$04]
Project5.dpr.14: y:= x;   //y sits on the stack frame.
004085F8 8B45FC           mov eax,[ebp-$04]
004085FB 8945F8           mov [ebp-$08],eax
Project5.dpr.17: z:= 0;    //z is also in the stack frame.
004085FE 33C0             xor eax,eax
00408600 8945F4           mov [ebp-$0c],eax
Project5.dpr.18: if (y = 1) then Inc(z);
00408603 837DF801         cmp dword ptr [ebp-$08],$01
00408607 7503             jnz $0040860c
00408609 FF45F4           inc dword ptr [ebp-$0c]
Project5.dpr.19: end;     //all vars stay in scope.
0040860C 8BE5             mov esp,ebp  //until the stack frame is dismantled.
0040860E 5D               pop ebp  
0040860F C3               ret 

So your situation should never occur with optimization off, but...

You can set optimization on/off in the source code too:

{$Optimization on/off}  or
{$O+/-}

If that line is in front of your routine it will override the global setting.

http://docwiki.embarcadero.com/RADStudio/en/Optimization_%28Delphi%29

Galloglass answered 6/6, 2011 at 19:46 Comment(4)
Hi Johan. This is what I am doing!!! I already set the Optimization to OFF in 'Project Options'. I don't see the point in setting it one more time to OFF in the PAS file. Especially that will be a true zoo when I want to switch from Debug to Release build. Probably I would forget to remove the {$O-} directive. But I am pretty sure this is just a Delphi XE bug. All in all they only released the Update 1 for Delphi XE. Right. We will have to wait for Update 2, 3, 4, 5.... and maybe even 6.Billbug
I'm just saying that you might have left a {$O+} in somewhere. Also you can break on the point before your var goes out of scope and right click for a menu, choose debug-> view CPU. Copy paste the relevant part in the question.Galloglass
"I'm just saying that you might have left a {$O+} in somewhere" - That was my point: I don't use this compiler directive just because I might forget about it. It is my rule. I will do a search for it but it will be useless since I never broke this rule.Billbug
@Altar, 1. what does the assembly code that Delphi generates look like. 2. try and put {$IFDEF DEBUG} {$O-} {$ENDIF}, what code does Delphi generate now? 3. Same as (2) without the {$IFDEF}.Galloglass
S
2

The code you posted does not compile as-is, so I can't be 100% I didn't kill the reproduction case by my personal modificications to make it run... but I cannot reproduce your particular problem. Anyone else who can?

Sure, the debugger/evaluator complains when optimization is on, but the problem definitely disappears with optimization off and a rebuild. Are you sure you did a proper rebuild?

I kinda disagree with Davids' statement that "we all suffer from this from time to time". Aside from known and predictable border cases (variables being out of scope with the breakpoint on end) I actually never run into this problem. As long as I prevent my coworkers from checking the dproj into version control with optimization on, that is.

Sanity answered 6/6, 2011 at 20:12 Comment(2)
You could be right, perhaps it's me that's doing something wrong. I've never really tried to hard to understand what exactly it is that causes me to use tricks like I described in my answer. I'm usually more interested in solving the problem at hand than looking under the hood.Munificent
@David That's probably a much healthier attitude than getting all overfocused on these minor productivity issues like me... then again, our juniors tend to ask about these things when they first encounter them, and I hate to have to answer them "ignore and fiddle until it works". Unless there is crunch, that is. :)Sanity

© 2022 - 2024 — McMap. All rights reserved.