Is it a bug that attempts to compile this code results in IDE terminating or the compiler failing to run?
Asked Answered
N

3

10

Beware of Exit command usage in inline functions! I have been using Delphi XE3 here.

Symptom

In certain circumstances, when a call is made to an inline function that contains Exit command, and the return value of the inline function is used directly in WriteLn(), the compiler reports an error message,

"dcc" exited with code 1.

or even worst, the Delphi IDE terminates without any confirmation.

function ProcessNumber(const iNumber: Integer): Boolean; inline;
begin
  if iNumber = 0 then begin
    Result := False;
    Exit;
  end;
  // some code here ...
  Result := True;
end;

procedure Test;
begin
  writeln( ProcessNumber(0) );
end;

begin
  Test;
  ReadLn;
end.

However, if the return value of the inline function is stored in a variable, and then the variable is used in WriteLn(), the problem does not occur.

procedure Test;
var
  b: Boolean;
begin
  b := ProcessNumber(0);
  writeln(b);
end;

Questions

  1. Is this a compiler bug?
  2. If this a bug, is there a workaround to safely exit from an inline function?
Nurse answered 7/6, 2015 at 9:30 Comment(2)
It makes me wonder, do you expect this to exit the caller context, or just the inline function ?Harmless
@Harmless I think asker knows that inline doesn't change what exit means. It's the internal AV that kills the IDE that is the problem.Haddington
H
9

This is certainly a bug. It occurs in all the IDE versions that I tested, XE3, XE7 and XE8. I honestly don't think there's a lot you can do. For me the IDE terminates on compilation every time. I think you'll just have to write the code in a way that does not lead to IDE crashes.

You can use the IDE option that forces compilation to use msbuild. This puts the compilation into a separate process and so ensures that the IDE won't crash. It won't help you much though because although your IDE will not keep dying, you still won't be able to compile your program!

When you build with msbuild, you get an error of this form:

error F2084: Internal Error: GPFC00000FD-004D3F34-0

The GPF stands for General Protection Fault, that is an memory access violation. This presumably is an unhandled exception that is killing the IDE when the compilation is performed in process.

My advice is that you submit a bug report to Quality Portal. That is the only way to get the defect fixed. Although do not expect a fix ever to come to XE3.

Haddington answered 7/6, 2015 at 9:51 Comment(3)
Heffernan, thanks for the answer. I have submit the bug to Quality Portal. I think, I'm forced to use goto labelExit as a workaround for now.Nurse
@Nurse - exiting is not always a problem. This seems fine f.i: Result := iNumber <> 0; if not Result then Exit; ...Bairam
@Nurse - I see an error when I click the link. Was the ticket moved? "It seems that you have tried to perform an operation which you are not permitted to perform. If you think this message is wrong, please contact your JIRA administrators"Propagandize
F
2

One workaround that you could use here is to reverse the if conditional implementation and thus avoid using of Exit command altogether.

So instead of using

function ProcessNumber(const iNumber: Integer): Boolean; inline;
begin
  if iNumber = 0 then begin
    Result := False;
    Exit;
  end;
  // some code here ...
  Result := True;
end;

use

function ProcessNumber(const iNumber: Integer): Boolean; inline;
begin
  if iNumber <> 0 then begin
    // some code here
    Result := True;
  end;
  else
    Result := False;
    //No exit needed here as this is already at the end of your method
end;
Fetid answered 7/6, 2015 at 13:13 Comment(3)
SilverWarior, I appreciate your comment, so +1 from me. However, in my example, I just show that it turns out the Exit command behaves unexpectedly in certain circumstance. My example does not really reflect my actual code structure. I'm sure every developer has ever faced a situation where Exit immediately from a function is the best available option in terms of efficiency. Anyway, I agree with you that sometimes (as in my example) avoiding Exit command does not reduce code performance.Nurse
I was suspecting that solution can't be so easy but still you would not believe how many times can you overlook even simplest solutions. Especially when you spend some time banging your head about solving some problem and forgetting to go and look at the big picture and try to perhaps avoid that problem in the first place.Fetid
@Silver The real code is probably larger and avoiding exit would make the function less clear.Haddington
P
0

In our case "dcc exited with code 1" happen when we passed an interface as "var" parameter.

I have found a workaround for this problem.

First of all, there were two bugs in one:

  1. The compiler could not show the error msg properly. This happens because the project was set to compile externally (in MSBuild). Once I put that option back to default, the compiler was able to show the actual error msg and the line of code/unit where it happens.

  2. Our framework had methods that received interfaces as var parameters. The 64bit compiler did not like that. The solution was to remove the var parameter OR to remove the [unsafe] decorator from the variable.

_

procedure DoStuff(var i: ISomeInterface);  // Fix a: Remove "var"   
begin   
   // DoStuff may set the I parameter to Nil!  
end;  

used like this:

var  
   [unsafe] x: ISomeInterface;     // Fix b: Remove [unsafe]   
DoStuff(x);  
Propagandize answered 28/6, 2023 at 10:39 Comment(1)
quality.embarcadero.com/browse/RSP-41902Propagandize

© 2022 - 2024 — McMap. All rights reserved.