1

I'm getting strange results when attempting to de-allocate a static based variable. Below is a small test program I've created to demo the issue I'm having. The static based variable is in the proc1 sub-procedure of this test program. Its name is myIx, with based pointer of myIx_p. I put comments in the main body of the program to indicate the issues that I'm having. What am doing wrong here?

 D ix              s              5i 0                                                       

  /free                                                                                      
   ix = proc1(*off);     // ix is 1 after this statement => Expected                          
   ix = proc1(*off);     // ix is 2 after this statement => Expected.                         
   ix = proc1(*on);      // ix is 0, which is expected.  But myIx_p is not being set to null => NOT Expected
   ix = proc1(*off);     // ix is 3 after this statement => NOT Expected.  Expecting 1.       
   ix = proc1(*on);      // try to shutdown again and get CEE0810 error => NOT Expected                          

   *inlr = *on;                                                                              

  *------------------------------------------------------------------------------------------
  * proc1 to test based static variable                                                      
  *------------------------------------------------------------------------------------------
 P proc1           B                                                                         
 D                 pi             5i 0                                                       
 D  piShutDown                     n   const                                                 
 D myIx            s              5i 0 based(myIx_p)                                         
 D myIx_p          s               *   static                                                

    // caller only wants to shutdown the proc        
    if (piShutDown and myIx_p <> *null);             
      dealloc myIx_p;                                
      return 0;                                      
    endif;                                           

    // allocate myIx if not yet allocated            
    if (myIx_p = *null);                             
      myIx_p = %alloc(%size(myIx));                  
    endif;                                           

    // increase the value by 1 as a test             
    myIx += 1;                                       

    return myIx;                                     

 P                 E                                 
  /end-free                                                                                          
HockChai Lim
  • 1,675
  • 2
  • 20
  • 30

1 Answers1

2

The answer is right there in your comments. You do not set myIx_p = *null after you dealloc. Failure to set it to *null means it is still pointing to the same memory location that it was only the operating system no longer sees it as allocated. The behavior you are seeing is entirely expected. The fix is as simple as:

// caller only wants to shutdown the proc        
if (piShutDown and myIx_p <> *null);             
  dealloc myIx_p;
  myIx_p = *null;                                
  return 0;                                      
endif;                                           

You can also resolve it as thus according to the IBMi documentation:

// caller only wants to shutdown the proc        
if (piShutDown and myIx_p <> *null);             
  dealloc(n) myIx_p;
  return 0;                                      
endif; 

If you don't use (n), you must set it to *null yourself like in the first example. See the documentation about dealloc here: https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/rzasd/zzdeall.htm

Player1st
  • 1,575
  • 10
  • 14
  • I see. A bit surprise by the system continues to let the program use a de-allocated storage, which makes me think that the storage has not been de-allocated. – HockChai Lim May 07 '20 at 13:21
  • This is common across every major operating system. This is one of the reasons that pointers are considered dangerous and can lead to memory or security leaks. You will see the same behavior in Windows, Linux, Mac, FreeBSD, etc and on most programming languages with pointers. Allocation and deallocation isn't creating and removing memory. All of that is fixed already (hand waving virtual memory and other stuff aside). Allocation and deallocation is simply a program informing the operating system that you would like to reserve or release a memory location. Either way, it still exists. – Player1st May 07 '20 at 14:57
  • somehow I thought IBM i has some protection against that. If I recall correctly, I believe a called program will error out if caller program passes a field of 30 chars to the called program that accepts a 50 chars param. It errors out when called program tries to access anything that past the first 30 chars. – HockChai Lim May 07 '20 at 15:54
  • 1
    As with almost everything to do with memory accesses, the answer comes down to "it depends". I think the most relevant issue here is that you are talking about memory allocated on the stack vs memory allocated on the heap. I don't want to get too deep into operating systems and compiler theory here but its suffice to say the stack and heap have different behaviors based on both how the compiler and the operating system treats them. – Player1st May 07 '20 at 16:34