Stack Corruptions

Stack corruptions can occur for a variety of reasons. To understand why and how they occur, you need to understand the differences between z/OS and the distributed platforms to which you are migrating.

Parameter Passing: z/OS vs. Open PL/I

On z/OS, parameters are passed via a well-defined convention. Over the years, clever programmers have written code that relies completely upon this convention, which means that this code will not run in a distributed environment such as Open PL/I without changes.

z/OS
When a z/OS compiler generates a CALL or invocation of a function, regardless of language used, it uses a standard calling convention. One of the mechanisms that is part of this calling convention is setting up R1 (Register 1) so that it points to a memory location containing the address(es) of the parameters and any parameter descriptions required by the program or function called. The end of the list of parameters and descriptions is delimited by the last parameter in a 32-bit register that has the "high order bit" turned on (set to 1). Unfortunately, this convention allows some sloppy practices such as a calling program not passing all parameters, or a clever assembler or C routine dynamically detecting the last parameter to avoid the pitfalls that can happen when code in the caller does not match the the code in the called.
Note: The same issue can exist between PL/I, COBOL, etc.
Open PL/I
Open PL/I follows the parameter-passing convention native to the platform or operating system to which you have migrated. This is typically referred to in computer science literature as the ABI (Application Binary Interface). It refers to what registers are used for what purpose, whether parameters are pushed onto the stack or passed in a different manner, etc.

Common Causes of Stack Corruptions

The ENTRY declaration for a called procedure does not match the PROCEDURE definition within the called PROC
A stack corruption can be caused by a difference between the number of parameters and/or the attributes of the parameters. For example, it could cause a stack corruption when the caller claims to be passing an array with ten items, but the called procedure claims to be receiving an array with 20 items. See Parameter passing: z/OS vs. Open PL/I above for a discussion of how this can be problematic.

Solution: Ensure that the passing and receiving arrays match. A field-developed solution to remediate this issue when it is widespread across the codebase is available from Micro Focus Customer Care. The Enterprise Analyzer product can also help identify this scenario.

A pointer to an AUTOMATIC variable is passed from one routine to another using unmatched pointers
In this scenario, the stack corruption occurs when the variable in the called routine based on this pointer is declared to be larger than it is in the caller. An assignment into that variable corrupts the stack at the location after that variable. The severity of the issue is completely dependant upon what is corrupted and where.

Solution: Check to be sure that the size of corresponding variables in the caller and the called routines match.

A pointer to an array is passed between two procedures, and the array is declared with different array bounds between the two procedures
Solution: The proper coding practice is to have the called program or function declare the array bounds with an * (asterisk) so that the passed array descriptor causes the called program or function to generate the correct code.

Increasing Stack Size

On Windows platforms, you can increase the stack size to reduce the possibility of trouble due to reaching the stack size limit. Use the following syntax:

LINK /EDIT /STACK:stack-size[,commit] cassi.exe

Where stack-size is a the number of bytes. For example, the following command increases the stack size to 8 MB:

LINK /EDIT /STACK:8000000,8000000 cassi.exe