'Cobol MCH3601 error when calling C program

there is a MCH3601 when calling a C program in COBOL multiple times. In the first calls, it works well, but then it fails with that error (MCH3601)... I call the C program like this

CALL "C2" USING BY REFERENCE RESULT-STRING.

The strange thing is that if I call a different C program before the call that fails, then the call that was failing works well. I am familiar with bugs in C in which you put an additional printf and everything works, and those are because you are allocating memory poorly and the fact of using a printf allocates more space in the stack for the return address of the printf and its parameters, so your bad code works because is overflowing over the printf stuff so no segmentation fault.

I guess this is something similar, but in cobol I have variable declarations like this

01  RESULT-STRING    PIC X(20)       VALUE ALL "X".

So I believe that should allocate the resources it needs. Also I have no idea about as400 assembly and I am somewhat ignorant in as400 so I am struggling to tackle the problem. Thanks for any help.

--EDIT

to answer comments: The C program returns an int. It is defined as

int main(int argc, char *argv[])

The argument is obtained as

char * myarg=argv[1];

and then other string is copied into it:

char * other_string[100];
...
//I null terminate it at byte 16
other_string[15]=0;
//the strcpy will copy only 15 bytes plus null char into the referenced arg
strncpy(myarg, other_string,16);
return 0;

So I believe I am not writing over something outside the referenced cobol variable in C in any way. The Cobol code is rather large and it does multiple calls in different places.

Is it possible to have an overflow in Cobol that mess the return address of the call or something like that?



Solution 1:[1]

Your Cobol routine passes one parameter by reference, i.e. it passed the address of the storage area of variable RESULT-STRING. So, your C routine will receive a single parameter, i.e. a pointer.

What you assume to be the integer containing the number of arguments passed, argc, is actually the address of the single parameter passed by reference. All the references to the argv array use arbitary storage adressses, since nothing has been passed.

You need to make sure that the entry point to the C routine is correctly specified, since you call C2 from Cobol. Your C routine should be declared as:

void C2 (char *result-string)

Only if the C program is the top-most routine, called form a command line like environment, will it be passed a counter, and an array of char pointers to the arguments given.

Update

I've coded a sample Cobol routine calling a C routine, passing one parameter by reference. Note this was done on z/OS, not AS/400. You man need to adjust to the AS/400 environment.

Cobol Source

       IDENTIFICATION DIVISION.                                     
       PROGRAM-ID. COBTOC.                                          
       AUTHOR.     Peter Hunkeler.                                  
       ENVIRONMENT    DIVISION.                                     
       DATA           DIVISION.                                     
       WORKING-STORAGE SECTION.                                     
                                                                    
       01  Some-Char-String   PIC X(20) value is 'Hello from Cobol'.
       01  C-SubRoutine       PIC X(8) VALUE 'CFROMCOB'.            
                                                                    
       PROCEDURE      DIVISION.                                     
                                                                    
           DISPLAY 'About to call subroutine ' C-SubRoutine.        
           DISPLAY 'Passing Some-Char-String: ' Some-Char-String.   
           CALL C-SubRoutine USING BY REFERENCE Some-Char-String.   
           DISPLAY 'Just returned from ' C-SubRoutine.              
           DISPLAY 'Some-Char-String now is: ' Some-Char-String.    
                                                                    
           MOVE 0 to RETURN-CODE.                                   
           GOBACK.                                                  
                                                                    
       END PROGRAM COBTOC.                                          

C Source

#include <stdio.h>                                      
                                                        
void cfromcob( char *pCobString ) {                     
                                                        
 char string[21];                                       
 char returnString[21] = "Returning from C   ";         
                                                        
 printf( "Hello from some C code.\n" );                 
                                                        
 strncpy( string, pCobString, 20);                      
 string[20] = 0x00;                                     
 printf( "This data was passed: %s\n", string );        
                                                        
 strncpy( pCobString, returnString, 20);                
 printf( "This data is returned: %s\n", returnString ); 

 }                                               

The C routine was bound with the following BINDER parameters:

  ENTRY    CFROMCOB
  NAME     CFROMCOB(R)     

Runtime Output

When run, the following lines are seen on the output (SYSOUT):

About to call subroutine CFROMCOB             
Passing Some-Char-String: Hello from Cobol    
Hello from some C code.                   
This data was passed: Hello from Cobol    
This data is returned: Returning from C   
Just returned from CFROMCOB                   
Some-Char-String now is: Returning from C     

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1