One of the more obscure error messages you can get at run time is Access Violation, which the Visual Fortran run-time library reports as error number 157. The documentation says that it is a “system error,” meaning that it is detected by the operating system, but many users think they’re being told that their system itself has a problem. In this article, I’ll explain what an access violation is, what programming mistakes can cause it to occur, and how to resolve them.
Windows (the 95/98/Me/NT/2000 varieties) is a 32-bit virtual memory operating system. The “32 bit” means that a memory address is 32 bits in size, potentially having over four billion possible addresses. “Virtual memory” means that not every memory address in use corresponds 1-to-1 with a physical memory address – some may be “resident” in RAM and others “paged out” to a disk file. The other important aspect of virtual memory is that only those address ranges currently being used exist at all – others are not represented. It’s like a telephone book, which has pages for only those names of people who live in the city. If a phone book had to include a space for every possible name, every city and town’s phone book would fill rooms!
When your program starts to run, Windows allocates (creates) just enough virtual memory to hold the static (fixed) code and data in the executable. As the program runs, it may ask to allocate additional memory, for example, through calls to ALLOCATE or malloc, either directly by your code or indirectly by the run-time library. Each allocation creates a new range of now-valid virtual addresses which didn’t exist before. When the program ends, Windows automatically deallocates all the virtual memory the program used.
Since not every possible 32-bit value represents a currently valid address, what happens if you try to access (read from or write to) an invalid address? Yes, that’s right, you get an “Access Violation”! Probably the most common address involved in an access violation is zero. Because a zero address is typically reserved as meaning “not defined”, Windows (and most operating systems) deliberately leaves unallocated the first group of addresses (page) starting at zero. This means that an attempt to access through an uninitialized address will result in an error. You can also get an access violation trying to access memory with a non-zero addres s when that memory’s address range hasn’t yet been allocated.
Common causes of the “invalid address” type of access violation are:
- Mismatches in argument lists, so that data is treated as an address
- Out of bounds array references
- Mismatches in C vs. STDCALL calling mechanisms, causing the stack to become corrupted
- References to unallocated pointers
Another type of access violation is where the address space exists but is protected. Usually, the address space in question is set up as “read only,” so an attempt to write to it will result in an access violation. In Visual Fortran, the most common cause of this is passing a constant as an argument to a routine that then tries to modify the argument. Visual Fortran, as of version 6, asks the linker to put constants in a read-only address space. Windows NT/2000 honors this, so trying to modify a constant gets an error, but Windows 95/98 (not sure of Me) does not, so the modification is allowed. This is why some programs that run on Windows 9x don’t on NT/2000. (It is a violation of the standard to modify a constant argument.)
If you are running your application in the debugger, the debugger will stop at the point of the access violation. You may need to use the Context menu in the debugger to look at the statements of a caller of the code where the error occurred, but this can usually give you a good idea of what might be wrong. Compare argument lists carefully and look for the mistake of trying to modify a constant. Rebuild with bounds and argument checking enabled, if it’s not already on (it is by default in Debug configurations created with V6 and later).
So now you know that when you see “Access Violation”, Windows is trying to tell you “Don’t Touch Me There”.
Note from Steve – As of December 2005, Intel Fortran does not put constants in read-only image sections. That will be enabled in an update due in January 2006. Current versions of the compiler do support the
switch which tells the compiler to pass constants in a stack temporary so that the called procedure can safely store to it, with the changes being discarded on return.
(From Intel Developer Zone, copied with permission)