06230551.txt 23-Jun-00 Drowning in a sea of 5333 Errors! Posted by: JOHNROE HELP!!! From the outset we've been plaugued by 4660 errors in our large VO2 application, and whilst some of our 50+ sites have been tollerating it, others are understandably getting pretty fed up. Now we've ported the app to VO2.5 and sure enough, we found loads of 5333's caused by nasties from a byegone age, and have spent the last three weeks putting right these past sins. However, the app is still remarkably flaky, and is not even ready for first testing. Unless we set DyneSize(40), we can't keep it up above a couple of minutes --- not a pretty sight! We've studied the stitaution in detail, read Rod da Silva's article till we can recite it backwards (almost), and have tried just about everything we can think of --- and still no joy. We've opened and altered EVERY binary entity, re-indexed the repository, exported and re-imported modules, revisted all the dbServers and made sure we close everything properly, and set objects to NULL_OBJECT. Still, when the Garbage Collector kicks in, (we have a Garbace Collect button on hand and perform the ceremony at will!) its inevitable that the app will die almost instantly. All we can imagine is memory corruption on a massive scale! Even WipeDynSpace has not helped us. Does anyone have any ideas, or can recommend anything short of valium or an extremely sharp knife? Growing greyer by the day! John M Roe RE: Drowning in a sea of 5333 Errors! Posted by: williem John, My understanding about the DynSize function is that it allocates pages of dynamic memory that are availably for VO. The Garbage collector will try to free up the memory. The larger the program, the more dynamic memory you might require. I initially went with dynSize(40) based on stuff I read from Larry Atkins (ReportPro). You might have to go to a higher dynsize to give yourself enough dymamic memory to let the garbage collector do it's thing. On my com programms (using VOCOM or 25's native), I have to close out each method with the if !incollect() collectforced() endif Otherwise, after the program has ben running for a while, it will run out of dynamic memory and abort. Not good when it is running under IIS. Here is the skeleton that I use: Method somemethod() class myWebService LOCAL nRet AS LONGINT LOCAL oError AS USUAL LOCAL bErrBlock AS CODEBLOCK LOCAL oRS AS ADOServer LOCAL cSQL AS STRING bErrBlock := ErrorBlock({|oErr| _Break(oErr)}) #IFDEF __DEBUG goLogFile:DebugMsg("getting next Distributor Number") AltD() #ENDIF BEGIN SEQUENCE nRet := 0 // make sure that the database is really open IF SELF:openDB() cSQL := "select LastDistNun from LastDistNum " oRS := ADOServer{cSQL,oConn,NIL,NIL,NIL} IF oRS:BOF .and. oRS:EOF // no records BREAK 1 ENDIF nRet := oRS:FIELDGET(#LASTDISTNUM) oRS:FIELDPUT(#LASTDISTNUM, nRet) oRS:update() oRS:Close() ELSE BREAK 0 ENDIF RECOVER USING oError #IFDEF __DEBUG goLogFile:DebugMsg("Error retrieving distNum") #ENDIF IF IsNumeric(oError) DO CASE CASE oError = 0 #IFDEF __DEBUG goLogFile:DebugMsg("Error opening database") #ENDIF CASE oError = 1 #IFDEF __DEBUG goLogFile:DebugMsg("Error no records found") #ENDIF ENDCASE nRet :=0 ELSE // pass on the error block nRet = -99 // VO runtime Error // Eval(bErrBlock, oError) ENDIF END SEQUENCE ErrorBlock(bErrBlock) oRS := NULL_OBJECT IF !inCollect() CollectForced() ENDIF RETURN nRet RE: Drowning in a sea of 5333 Errors! Posted by: JOHNROE Hi Willie Many thanks for the tips - You've clearly had it bad too! My collegue and I are about to start hunting around modules for any other hidden nasties - redundant defines etc which may be hidden, but we'll also take a good look at the skeleton you kindly sent. From the research we've done, it looks as though pointers are getting corrupted by the garbage collector - in fact we took some ideas from Rod's SDT article, and actually saw pointers being changed as the GC did its bit. What we can't work out, is how the hell to stop it. We'll also up the Dynamic Memory, but I'm not sure at what point that could cause problems of its own - if the user has insufficient RAM, will the whole app fail to run anyway? At the moment its split into a 5.2Meg EXE and a 3.5 meg DLL, so as you can see, there's one hell of a lot of work to do! Anyway, thanx again and I'll keep you informed. Kindest John RE: Drowning in a sea of 5333 Errors! Posted by: Stefan Dietl Once (20b) I used a inifile class with api-calls using string2psz(cstring). After removing those api-calls by using stringalloc(cstring) I got a much more stable app with less 4660. Another stupid mistake I made was to create an order to a field not existing in the table. VO will not give an error, you can open a bad indexed file many times without crashing - but the GC will not forgive You... Perhaps not really news... good luck Stefan RE: Drowning in a sea of 5333 Errors! Posted by: JOHNROE Hi Stefan We're exploring ALL avenues, so any help is appreciated. Thanx John RE: Drowning in a sea of 5333 Errors! Posted by: mlincoln John, As you may have realized, the problems you are experiencing result from dynamic memory being moved by the garbage collector thus invalidating a pointer to said memory. You should take extra care to review any areas in your code that might cause this. The classic is casting or converting a string to a psz. Allocating a true static string using StringAlloc() solves this problem. I have some experience with finding these type of problems, so if you would like some assistance, let me know. Mark RE: Drowning in a sea of 5333 Errors! Posted by: Marek W. Zawolek Hi, I in the middle of dealing with a similar problem. Let me tell you about some of experiences. I have a large VO 2.0 application thet was working almost fine, only occasionally having some unexpected problems that I tracked down to GC messing my arrays to the point that for instance ALEN() was reporting thousands of elements instead of just a few. With VO 2.5 things went so wrong that the application was dying almost every time. Playing with VO 2.5 by "try anything" I noticed the following: 1. my application was first reading all report definitions (my own simple report-writer), macro compiling them end executing 2. all the definitions were being stored in collections (1- dimensional arrays of objects, each holding all the definitions for a single entity) 3. VO 2.0 stopped having ANY problems and VO 2.5 improved after (SURPRISE!!!) instead of loading the definitions to each object through INIT ther was calling SUPER:INIT (the default generic for each object), I leaved INIT as default only and I was loading data through another method called after the object was instantated. It sounds strange, as it should have no effect, but somehow GC was OK in 2.0 and less corruptive in 2.5. 4. With 2.5 I noticed that if I run my report with small amount of data so GC does not kick-off during the reporting and then I run a second report with the large amount of data, everything goes fine, but starting with large amount of data almost always ends with 5333. CollectForced before and after some big operations did not help. So thanks to 2.5 my 2.0 application became absolutly stable, but I still cannot have my 2.5 version running. I KEEP WORKING ON IT!!! Good luck, I am happy to be in a good company. Marek RE: Drowning in a sea of 5333 Errors! Posted by: JOHNROE Thanx Marek Glad to see we're not alone - I just wonder how many folk are struggling with this one, or just keeping quiet and hoping that it will go away! There is a big problem with the GC shifting things around and we have created a situation where we've seen pointers change after the GC's kicked in, exactly as Rod da Silva pointed out in his article for SDT. The big issue is, how exactly do you stop it! Also, if we use DyneSize to allocate more memory, and stave off the problem, what are the guidelines. Should teh default size work, or should we experiment and find a suitable value. It would be great if someone could give some definative answers, as this is costing us a lot of money now. We are trying to ship a big multi-user app to about 50 clients, and just daren't send it out. We can't even do our in house testing as the app is too unstable. We can mask it by ramping up DynSize, but gather that this is not really the answer. Lets just hope that one day someone might come clean on this. Regards John RE: Drowning in a sea of 5333 Errors! Posted by: Marek W. Zawolek Hallo again, I really feel better, because for quite a while I thought that it is just my sloppy way of programming responsible for all this mess. I have to admit that now when I increased DYNSIZE to 40 my VO 2.5 application behaves much better and observing 2.0 I noticed that it was much easier with my app to get DYNSIZEINFO size over 200 whereas 2.5 always keeps it at minimum e.g. 40. My guess is that 2.5 gets into errors when it tries to increase DYNSIZE by itself. As things improved with my app after moving filling objects from INIT into some other METHOD called after initialization, perhaps you can try to do it with your app. Also remember to NULL_ARRAY all your instance arrays and NULL_OBJECT all your instance objects in the CLOSE method of your objects. I admit it maybe quite time consuming (it took me days as I had plenty of this kind of objects), but otherwise we have to wait for 2.5B - it looks like VO gets better with B releases. Good luck Marek RE: Drowning in a sea of 5333 Errors! Posted by: Marek W. Zawolek Hi John, "Playing" with VO 2.5 I just noticed that setting your memory with DYNSIZE only once may not be enough. It looks like VO 2.5 tries to be smart and occasionally it reduces dynamic memory later even to 20 instead of 40 set by DYNSIZE. Therefore in some critical places I have added the following code: IF DynInfoSize() < 40 DynSize(40) ENDIF The appication behaves much better. Regards Marek RE: Drowning in a sea of 5333 Errors! Posted by: sburak Hi John, in addition to what others say, put this code in your Close() Methods WHILE TRUE ApplicationExec( EXECWHILEEVENT ) IF ! InCollect() CollectForced() EXIT ENDIF END This is in my oppinion better then IF ! InCollect() CollectForced() ENDIF However, my experience is that most of the 5333/4660 errors arrive from bad coding, ie referencing to objects that are out od scope etc. Hope this helps little bit, Senad Burak RE: Drowning in a sea of 5333 Errors! Posted by: JOHNROE Hi Senad This sounds a useful tip and its going in right away! Thanx John RE: Drowning in a sea of 5333 Errors! Posted by: hourant Hi Senad, I'm not sure that Collecforced() solves the 5333 error. AFAIK, this just runs the GC collector to work more often than usual. If the coding is properly done you shouldn't force the GC to work by yourself. But this should shows the 5333 error closer to the point where the error really is. I totaly agree with you about the bad coding and the object that are out of scope. We have reduced drasticaly our own 5333 errors with the registeraxit and axit method. Now, when we create an new object, the first things we do is to place a registeraxit(self) in its init method and create an axit() method that calls a destroy method. Even if there is nothing to clean, the method is there and I can be sure that it will be called by the GC. Another trick is to display the number on axitregistered objects on the status bar. This number should always be very low when trese is no opened "object". When you leave a window, this value should come down to the value it was before opening the window. You should check Geoff Canvas sample (I think it's on knowvo.com). With 2.5x, we have wiped off all the collectforced with used to use in 2.0. Just my 2 cents. HTH Eric RE: Drowning in a sea of 5333 Errors! Posted by: Paul Bartlett Senad, In my experience putting an ApplicationExec() in Window close routines can cause other side effects. Users who are fast with their mouse can start clicking around the application, or even close the app before your child window close method has finished. Best wishes, Paul Bartlett RE: Drowning in a sea of 5333 Errors! Posted by: hourant Hi John, Unfortunatly, I cannot give you THE answer to solve the 5333 errors. Every time I got this error, I have found the solution in my own code. One of our customers reported a 5333 error a few months ago. Updating his video drivers solved the problem. We have quite large applications running and no one has reported this error for a long time. I also think that NT is much more stable than 9x and we advice all our users to use this OS Eric RE: Drowning in a sea of 5333 Errors! Posted by: JOHNROE Hi Eric Thanks for the info. Regards John RE: Drowning in a sea of 5333 Errors! Posted by: Arne Ortlinghaus Hello John, perhaps you could insert an additional Testfunction which is enabled/disabled by a global switch which makes the following: if !_DynCheck() MsgError ("Error in Memory " AsString (DynCheckError())) endif if !InCollect() CollectForced() endif And then insert the function in as many places as possible. (It makes program much slower) Perhaps you see an error a bit earlier. The problem is that if the error happens in the garbage collector it is too late to see the reason. The other thing is that in my opinion there can be still problems in arrays that contain objects which are referenced in other arrays. Although in our sight every thing seem to work quite well at the beginning I had problems when buffering too much data in "global arrays" with too complex referencing the objects in the array. Maybe the garbage collector does not always know what to do. Another thing could be to look at objects that have a destroy-Method. Perhaps you can insert a protect-variable that disables the second call of the inner part of the destroy method. And perhaps after using a modal dialog or other objects with a Destroy-Method that you destroy it yourself and than set the variable to Null_Object. And afterwards call the testfunction above. Arne Ortlinghaus RE: Drowning in a sea of 5333 Errors! Posted by: JOHNROE Hi Arne Thanx for the info - all ideas are welcome. Also the DynCheck sounds useful to try. Kind regards John RE: Drowning in a sea of 5333 Errors! Posted by: TomWalden John, FYI, I've finally gotten rid of all but one scenario of my "Access Violation" (error codes 50 _{038}_ 5333) problems. In addition to using 2.5a1 with it's new fixes, I made the following changes in my code that corrected most of the problems. I realize that others have mentioned these and other suggestions, but these are what finally worked for me, so here is my 2 cents worth: 1. I was using global arrays (about 15) for use in all my various comboboxes. Instead I made a global oShell object and made all those arrays as instance variables in that shell class. 2. I strong-typed all of my methods in ALL of my classes. I also used the ~"OpenEarly /-" declaration in each of my "class - declare method" source code. 3. I made as many LOCAL variable objects early bound as possible. Whenever I was through with an object used in a method (or function), I would set that object := NULL_OBJECT (especially for dbServer objects) to help the garbage collector. When I was through with arrays I also set them to NULL_ARRAY ( a biggee ). 4. After setting my NULL assignments (like when closing a window), before and after calling a ReportPro object, and after calling a ListView:DeleteAll() methd, I inserted the following code: IF !InCollect() CollectForced() ENDIF I also did a CollectForced() firtst thing in the :Start() method of every app. 5. In a third party browser (bBrowser), it did not like macro expansion of field names for setting column color assignments. I replace the area with the macro logic with a large case statement and it works fine now. Go figure. The bottom line is that most of the changes were converting as much as possible into OOP logic and the other was helping out the garbage collector. Although I still think that VO has some memory handling problems, at least almost everything is working right now due to some coding changes. HTH, Tom RE: Drowning in a sea of 5333 Errors! Posted by: mrg17 Do you ever write code like FOo(x:=y(),z) ? If you look on the news groups you will see I posted last week (I have been away since) about a problem that if y() triggers the GC then Z (not x) is invalidated. This seems to have help A LOT with out 5333 problem. Note that we detected this using many things but IsDynPtr was a great help.