Silverfrost Forums

Welcome to our forums

Initialization to zero

1 Sep 2017 7:34 #20082

Steve

I don't have access to the required information at the moment so I can't respond fully to your query.

/UNDEF is designed for use when developing your application. Switch it on and test every path through the code. In other words, you only need to test for undefined variables once. The same principle applies to /CHECK and /CHECKMATE (which is /FULL_UNDEF). These options add a significant overhead to the code size and speed and normally are not helpful once every path has been checked.

1 Sep 2017 8:05 #20083

Thanks. Eddie. But we now have no choice but to go for our source code to be DLL - called from a Delphi wrapper.

I see no reason why DLL should be compromised by the compiler options, as DLL is permitted as an alternative to EXE.

It seems that /ZERO has changed since v6 and I just wonder if the /LO is doing what it is supposed to do, but with an unfortunate size implication. Hopefully, Paul can enlighten us.

And why should /LO increase the size of the DLL/EXE, when /ZERO did not need to in v6 ?

Steve

1 Sep 2017 4:19 #20086

The only thing that I can add at the moment is that /ZEROISE has not changed. Also we may need some sample code that illustrates the issue that is causing a problem.

1 Sep 2017 5:44 #20087

Steve,

Don't you archive the source for old versions? If you have that source code, you could do a trial compilation and run with FTN95 8.10. If it works, then the problem can't lie with the change of compiler versions but with something else you are doing. If it doesn't work, then it is definitely something for Paul to investigate. At the moment there is no proof that the problem relates to the compiler.

Alternatively, does your Delphi / DLL version work properly when compiled with your previous version v6 FTN95? Again, if it does not, then the problem lies with your changes, if it does work, then the problem is in the compiler.

If you no longer have the source code for the version without the Delphi wrapper / DLL, (or a computer with v6 FTN95 installed on it) then the chance of finding what is going wrong has decreased dramatically!

Eddie

1 Sep 2017 7:36 #20088

I have frequently come across one situation in which compiling with /UNDEF causes spurious aborts: a subprogram saves a copy of an argument, often an array argument. Later, the subprogram changes the value(s) of the argument before using the previous values. When the copy is made, undefined values are used and an abort occurs, even though that copy (or the undefined original) would never be actually used were the program allowed to continue executing.

Other than in the case that I just mentioned, using /Zero, /Save, and other subterfuges to suppress compile time or run time errors does more harm than good. I tend to be sceptical about codes that need such subterfuges to run.

It would be a good investment of your time and effort to determine the causes and implement a proper fix, rather than attempting to keep the problem hidden.

4 Sep 2017 1:16 #20097

I've run across occasions where the actual computed DATA causes the /UNDEF to get triggered. While it is not common, it can occur.

In my case, I was building a bit-mapped image in memory, with each byte being bit-wise set. Occasionally, the bit pattern in the character1/integer1 would become the hex pattern 81, and the /UNDEF would get triggered.

In the old days (1960's/70's) on the IBM 7040, there was an actual opcode to set the contents of memory with a bad parity bit. Access (read) this data, and it was trapped. The ultimate in /UNDEF. Alas, those days are long gone, and now a specific pattern has to be used.

While this bit pattern idea does work, it has some limitations.

4 Sep 2017 9:32 #20103

Thanks for the latest replies.

The whole point is that it was only a change of compiler from v6 to v8.1 that highlighted the problem and not the change of code with v8.1.

Only now, when reading up the definition of /ZERO, is it a puzzle that v6 worked at all, ie that local variables must have been getting initialised, because they should not have done so according to the documentation. The places we have found wanting in v8.1 so far, on a revisit to v6 worked fine.

If /ZERO has not changed, as Paul points out, this suggests that something else in the v6 compiler must be doing the initialisation : what other explanation is there ?

Certainly, amending the 'old' code to initialiase the offending variables with v8.1 works fine. We appreciate Paul's advice in attempting to identify these places in the 'old' code, but this would be a massive undertaking at the moment. We shall definitely need to do plenty of testing.

But I would like to re-emphasize the /LO option. Using it did not overcome the problem ! as I said before, with such a big overhead due to product size, it does seem to be a restrictive option.

5 Sep 2017 6:17 #20126

Steve

The option /LOCAL_ZERO is for .NET only (i.e. /CLR). Also it can't be used with /CHECK or any option that implies /CHECK such as /UNDEF and /CHECKMATE.

/LOCAL_ZERO was added at the request of a major user of .NET FTN95 and has only been implemented for .NET.

I don't understand how you can have used /LOCAL_ZERO because without /CLR you get a compile time failure and presumably you are not aiming to create a .NET assembly.

More to follow...

5 Sep 2017 6:36 #20127

Steve

You refer to the option /ZEROISE and also that you have moved from using a Fortran executable to using a Fortran DLL.

My first question would be, do you have shared data/variables in the DLL (i.e. data/variables that are shared between different functions and subroutines) and, if so how are these values initialised and shared?

If you only use local variables and pass other values as arguments in function/subroutine calls then it would be a simple matter to find out what /ZEROISE does in that context.

5 Sep 2017 7:16 #20128

Steve

Regarding your experience when moving to a different version of the compiler, I would recommend that you keep an open mind concerning the source of the problem. Since you are apparently using uninitialised variables, it is quite possible/likely that a change in the compiler or the operating system has simply exposed an existing user programming error. For example, an uninitialised variable might consistently have had a zero value say (by chance as it were) simply from of the context. Any change could expose the fault by using a different garbage/random value.

5 Sep 2017 8:17 #20129

Thanks, Paul

I would like to think it was never intentional to use unintialised variables, simply that with /ZERO in place, they happened to get initialised and so would never be spotted - until now !

Are you suggesting, Paul, that - quite mysteriously and quite by happenchance - that these variables were consistently being initialised in v6 and all of a sudden they are not now in v8.1 or v7 whenever ? Surely, this change would need to be by design or intention ? For the same reason that using /LO does not intialise these variables, ie the compiler is not actually doing the job it was supposed to do.

5 Sep 2017 9:01 #20130

Steve

I am suggesting that you keep an open mind. It is too easy to blame the compiler. As I have tried to explain, if you use /LO then the compiler will tell you that /LO is only provided for use with /CLR. Unless you are creating a .NET assembly, /LO is not an option for you.

5 Sep 2017 12:33 #20131

The Fortran Standard has a delightful and all-encompassing phrase, 'behavior undefined'. That may apply to your program, especially if the program has instances where variables are used without having been previously defined.

'Undefined' means 'anything can happen, or not happen'.

Your program may work correctly for a long period, and you may not even know that there is a problem. Without warning, one day you start getting incorrect results, or the program crashes, and you may start casting doubts on a compiler or OS update. Other events covered by 'undefined': running your program empties my bank savings account, or causes NK missiles to be launched at Mongolia, or causes a butterfly to flap its wings in Madagascar.

Bite the bullet now; diagnose and fix the bugs in your program. There is no known compiler with a /just_give_me_the_correct_results option.

6 Sep 2017 4:45 #20155

Thank you mecej4, we are resigned to your point, now that we are staying with v8.1.

Finding 'External exception' or Invalid floating point operation' has now happened a few times since moving compilers to v8.1 and employing tracing - sending messages to DebugViewer - identifies poor programming.

But, I have just come across one instance where introducing trace statements actually makes the program work ! I remember noticing some 'old' code where a statement had been broken up with an accompanying note that the compiler at the time was unable to process the original statement correctly.

Do the forum have any advice that can help overcome my problem ? Compiling the offending routine with /UNDEF or with /ZERO makes no difference to the outcome.

Thanks

6 Sep 2017 5:52 #20156

How to go about fixing your code is going to be mainly decided on the basis of how big your code is and what tools are available to you. If the code is not suitable for posting, that is one more hindrance.

FTN95 is great for small to medium size projects or projects that make use of graphics and Windows features, but there are other compilers and tools that I would consider using in parallel.

Sometimes, it is better to log a runtime error to a log file, take a reasonable corrective action, and proceed with execution, rather than abort execution on each message. The Lahey-Fujitsu compiler was good in that regard.

There are static code analysis tools such as FTNCHEK and Forcheck.

Floating point errors are routinely fixable if a traceback is available.

7 Sep 2017 8:54 #20160

Most appreciated. When our product was an EXE and compiling with v6, we used the traceback to great effect.

Our dilemma is that the 'offending' code - that needed trace statements inserted before working in the DLL form - compiled with v6 or v8.1 and without the trace statements worked fine as an EXE. As it has done for many years.

Compiling this same code in v6 or v8.1 but in the Delphi wrapper, ie. as a DLL, causes 'Invalid floating point operation' and 'External exception', until the trace statements are introduced. It would appear the traceback facility is no more when creating a DLL.

Does this suggest a Delphi involvement that needs addressing or the way we build our DLL ?

The LNK to create the DLL is as follows :

MAP product-name.MAP PERMIT_DUPLICATES NOSIZEWARNING DLL LO *.OBJ [ several instances ] LO named.DLL [ several instances ] EXPORTALL FILE product-name

Please login to reply.