In particular, what Cactus is currently doing is passing an array of size one to the Fortran routine. If the the compiler generates code that accesses this array as if it had the same size as a grid function, this should trigger a segfault. However, given the way the dummy variable is declared, there is actually accessible memory nearby so that there is no sefault. And since this is only a read access there is no bad consequence.
-erik
On Mon, Sep 26, 2011 at 4:15 PM, Erik Schnetter schnetter@cct.lsu.edu wrote:
I believe this statement is wrong, but lost the corresponding argument a few years ago.
- The Fortran standard doesn't say anything about C interoperability
(well, the new standard does, but we are not talking about these features). Thus it also doesn't speak about "not passing NULL pointers". In fact, the standard doesn't say anything about how variables are passed, or that they are passed by reference (as pointers).
Fortran does allow zero-length arrays.
From a system level perspective: If you allocate a zero-sized
memory region (via libc), then you may receive a NULL pointer. This depends on the implementation. Thus, if a Fortran implementation allocates a zero-sized array, it may also generate a NULL pointer.
- From a machine language perspective: If you have an array with zero
elements, then there are not too many actions you can legally do with it. You can compare the address of the array (i.e. the pointer) to other pointers, and it is conceivable that there may be a Fortran compiler that does check for NULL and then segfaults, but I don't really see the point of doing so. It would be extra work for no benefit. However, you obviously can't use the pointer to access memory, because the array has no elements, so any expression array(idx) would be illegal.
- The historic cases where passing a NULL pointer to a Fortran
routine in Cactus led to segfaults were cases of wrong compiler optimizations. I looked at some of the disassembled code, and it was clear that there were instructions generated to read array elements in cases where the source code didn't do so. For example:
pseudo Fortran: if (shift-has-storage) then bx=betax(i,j,k); else bx=0; endif pseudo assembler: load betax(i,j,k) into bx if not shift-has-storage: set bx to 0
Of course, the real code was more complex, and the compiler's optimzation made a lot of sense (performance wise, apart from being illegal). I reported this problem to Intel, and it was corrected in a later release.
So, let's change this piece of Cactus.
-erik
On Mon, Sep 26, 2011 at 3:56 PM, Roland Haas roland.haas@physics.gatech.edu wrote:
Hello Erik,
Regarding segfaults in Fortran: why don't unallocated variables lead to an error in Fortran? Do you refer to Fortran allocation or Cactus allocations here?
Cactus allocations. Variables for which no STORAGE statement is active (either global or in the schedule item).
The reason is that (see configs/*/bindings/include/cctk_Arguments.h) you cannot legally pass a NULL pointer as a FORTRAN array subroutine argument, there apparently *has* to be some storage (I guess FORTRAN does no allow zero-sized arrays). So for non-debug runs Cactus passes in the address of a dummy array. This is sufficient to prevent segfaults (even for rather larger grids). Caught me recently when adding the Multipatch hacks to support non-multipatch runs. I was counting on segfaults if I had forgotten any pointers (and for rather large grids, so it is not just a small grid issue that goes away in production runs). I ended up unitialized memory which was mostly 0 so it did not show up in the test (since the variable without storage was kxx in Minkowski spacetime). :-(
Yours, Roland
--8<-- configs/*/bindings/include/cctk_Arguments.h --8<-- /* * References to non-existing or non-allocated variables should be passed * as NULL pointers in order to catch any invalid access immediately * However, this runtime debugging feature may cause problems * with some fortran compilers which require all fortran routine arguments * to refer to a valid memory location (eg. to enable the code optimizer * to generate conditional load/store instructions if applicable). * For this reason, we pass NULL pointers only for debugging configurations, * and a pointer to a user-accessable memory location (a local dummy variable) * otherwise. */ --8<--
-- My email is as private as my paper mail. I therefore support encrypting and signing email messages. Get my PGP key from http://keys.gnupg.net.
Users mailing list Users@einsteintoolkit.org http://lists.einsteintoolkit.org/mailman/listinfo/users
-- Erik Schnetter schnetter@cct.lsu.edu http://www.cct.lsu.edu/~eschnett/