Re: Informix System Constraints
Posted in 1992
>From: uunet!fang.att.com!ebd (Elliot B Dierksen) >Subject: Re: Informix System constraints >Date: Sat, 7 Mar 92 9:08:03 EST >In-Reply-To: <199203060228.AA10396@das13.snide.com>; from "Dave Snyder" at Mar 5, 92 9:28 pm >X-Informix-List-Id: <list.929> > >I don't know why, but the guy I talked to seem to believe that there was some >bug that did not free memory when using single character constants in a WHEN >clause. I never made any attempts to test or substantiate this, but he seemed >pretty certain. Apart from the mention of single-characters, this is accurate enough. It actually affects any character strings. The following is a message I normally send out in connection with error number -4518 (no more temporary string space, approximately). Please note that some of it is fairly old (over a year), and that things have changed slightly. The newest information is at the bottom, after a shell archive. The code in the shell archive will probably NOT work with 4.10. This is one of those "features" which is, in my view (but probably not Informix's) a bug. Yours sincerely, Jonathan Leffler (johnl@obelix.informix.com) #include <disclaimer.h> ---------------------------------------------------------------------- STRING SPACE AND ERROR 4518 REVISITED. This item consists of the mail between J D Hicks and Elliot Danziger on dates between 1990-06-29 and 1990-07-02, followed by a description of some monitoring tools used at a client site to help the client detect the problem and neutralize the effects of routines which contain buggy code. The message ends with a shell archive of the C code used to implement the monitoring tools. The C code provides the following facilities which should prove useful in helping to isolate and detect code which causes the string space to be used irrecoverably. get_allocarea() set_allocarea() chk_allocarea() log_allocarea() Using get_allocarea() and set_allocarea() allows a buggy piece of code to be neutralised by the code which calls it. Using chk_allocarea() and log_allocarea() allows buggy pieces of code to be identified, though interpreting the data can be tricky. The story so far: >Date: Fri, 29 Jun 90 11:30:26 CDT >From: jdhicks@chicago (JD Hicks) >Message-Id: <9006291630.AA02016@chicago.informix.com> >Subject: -4518 error > >Help - > >I have a 'C' program that makes a call to 4gl functions. The 4gl functions >in turn call other 4gl functions, etc.. During the course of execution I am >getting a -4518 error, "The 4gl program can not allocate any more temporary >string storage". What are the possible reasons for this error to occur. > >Thanks in advance, > >J.D. > >Date: Mon, 2 Jul 90 07:18:29 PDT >From: elliotd@cougar (Elliot Danziger) >Message-Id: <9007021418.AA07143@cougar.informix.com> >Subject: Re: -4518 error > > Here is a repost of a response which discusses the root causes of the >4518 error. The 4GL training manual examples of reclaiming string space are >used in discussing the specifics of 4518 situations: > >* * * * * * * * * * > > There are two distinct data structures in use here. The "stack", which >is a dynamic array of 'value' structures, and the 4GL "string space" (for >lack of a better name) which is a fixed array of 10 'elalloc' structures >each of which point to a 512 byte block. > > Certain functions using the string space (retquote, using, ascii, etc.) >allocate the first available area in the array of blocks large enough to >hold the requested space. In the training manual example of 17 USING "###", >the first available 4 bytes (one for NULL) of the first available block will >be allocated to store the result of the USING (i.e. " 17"). If all 5,120 >bytes are unavailable, a 4518 is returned. When 4GL starts, none of the 10 >'elalloc' structures point to any space. The 512 byte blocks are dynamically >allocated with malloc to each of the 10 structures as demand for space >increases until all 10 blocks have been allocated. This space is never >released with free(). Instead, space is "reclaimed" by reusing the same >space for other functions that request space. The 'elalloc' structures >maintain an index into each block, representing the next available byte in >that block. When space is "reclaimed" a function ( acdealloc() ) is called >which simply sets all these indexes to 0, indicating that the next available >byte for each block is byte number 1. > > All this is fine except for one small problem - when should acdealloc() >be called? If it is called too soon, we will reuse space that is still in >use. If it is called too late we may run out of space. To this end the >calling of acdealloc() was made a function of the stack "movement". Whenever >a value is pushed onto the stack, and the stack pointer is pointing to the >*original* top-of-stack position, acdealloc() is called. The rationale >behind this is that at that point, whatever operation using string space was >in progress should have completed. > > To use an example, a C function uses retquote() to pass a string back to >a 4GL function. This allocates string space in one of the 'elalloc' >structures to hold the string being passed back, stores the address of that >string space in the 'value' structure pointed to by the stack pointer >(assume for now that the stack pointer was pointing to the top-of-stack), >and then increments the stack pointer (a push operation) to point to the >next 'value' structure (at this point, the string space is holding the >string being returned by the C function and should not be deallocated). The >4GL function uses popquote() to copy the string into a 4GL variable. This >decrements the stack pointer (a pop operation), gets the address of the >string in the string space from the 'value' structure, and copies the string >into the 4GL variable (at which point we no longer have need for the string >in the string space - it is already in the 4GL variable). Since the stack >pointer is now pointing to the top-of-stack, the *next* stack 'push' >operation will call acdealloc() and deallocate the string space. > > Looking now at the training manual example (first, the "right" way) > >let u = 17 using "###" >let u = u, f() > > which generates the following code (just the basic statements shown): > >pushint(17); /* Push arg 1 for _dousing(), stack_ptr incremented */ >pushquote("###", 3); /* Push arg 2 for _dousing(), stack_ptr incremented */ >_dousing(); /* Decrements stack_ptr once, formats the number with > ** the specified format, and leaves the result in the > ** value structure pointed to by stack_ptr > */ > >popquote(u,101); /* Decrements stack_ptr by one, puts the value of the > ** formatted string into the program variable 'u' - > ** the stack_ptr is now pointing to top-of-stack again > */ >pushquote(u,100); /* Since we are at top-of-stack, this push will