Link to home
Start Free TrialLog in
Avatar of Bruno Buesser
Bruno BuesserFlag for Switzerland

asked on

function return value in try...__finally block of C++ Builder

Hi

if have the following function:

int TItemFifo::GetCount()
{
	FLock->Enter();
	try {
		if (FHead >= FTail)
		  return FHead - FTail;
		else
		  return FArraySize - FTail + FHead;
	} __finally {
		FLock->Leave();
	}
}

Open in new window


The C++ Builder XE2 compiler reports the warning:
"W8070 Function should return a value"

I cannot understand this warning as the return value is definitely set in the try part. So I do not need to set a return statement at the end of the function outside the try..__finally block or inside the __finally part. When an exception occurs the return value can not be evaluated by the calling routine anyway as the program would jump to the next catch handler.
I never encountered this warning in a try...finally Delphi code.

Bruno
Avatar of pepr
pepr

The compiler assumes that the exception can happen before any of the return commands. Then the __finally branch would be used and there is no return. You have to add one to the __finally or just before the end of the method. The return command does not set the return value. It just causes the rest of code be ignored. There is nothing like a variable for implicit return. The return command is explicit and it returns the value of its argument.

This kind of warning is usual for any C++ compiler. It is not bound to try/catch. Simply some branch of the code leads to the situation when no return is specified -- but the function says it will return int.

The default code will probably return some value like zero -- because of that it is not considered error, but only the warning. It could be the case that Delphi defines the behaviour of functions when no return command is called. For example, the Python language documentation says that the value None is returned in such case. But it is a differen language. C++ wants you to be more explicit.
Avatar of Bruno Buesser

ASKER

My code is now:

int TItemFifo::GetCount()
{
	int ret = 0;
	FLock->Enter();
	try {
		if (FHead >= FTail)
		  ret = FHead - FTail;
		else
		  ret = FArraySize - FTail + FHead;
	} __finally {
		FLock->Leave();
	}
	return ret;
}

Open in new window


But return ret will never be executed when an exception occurs in try. Then the finally block is executed and the function is aborted at } of __finally just before the return statement. I tested this fact.
.  
I cannot put return into the finally block as the compiler will report an error.

I think the above modification with the ret variable is only to prevent the warning but basically is needless.
ASKER CERTIFIED SOLUTION
Avatar of pepr
pepr

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ditch the try-finally and go back to the try-catch, like this:
int TItemInfo::GetCount()
{
    int nCount = 0;
    
    Flock->Enter();

    try
    {
        if ( FHead >= FTail )
        {
            nCount = FHead - FTail;
        }
        else
        {
            nCount = FArraySize - FTail + FHead; 
        }
    }
    catch( Exception ex )
    {
        nCount = -1;
    }
    
    FLock->Leave();
    
    return nCount;
}

Open in new window

I like the labor division of catch and __finally. __finally ensures the releasing of resources requensted in try without dealing with the kind of error occured. catch performs error specific actions.
In my function I want do handle the exception in the calling routine but the calling routine is not aware about resources used in the function. So using  __finally gives me a short and easy readable code. Replacing __finally by catch yields more complicated code and would require to rethrow the exception and to call FLock->Leave() inside and outside catch.
So I prefer the solution of pepr to just call return 0 at the end of the function. It's needless code but prevents the compiler warning.