Abnormal Program Termination In A Turbo C++ Web Browser - html-parsing

I've been trying to make a workable web browser in Turbo C++ (I can't help it; I am supposed to work within the confines of my educational system). Essentially, what I have created is a simple parser that takes in a HTML file scans the text for tag delimiters, then identifies the tag, processes it using Turbo C++ default graphics library and then perform the required operation before outputting through an interface I created.
Essentially, I've been matching the cases in a long list of nested conditions. The problem is that execution has been falling through and for some reason I've been continuously getting the error of Abnormal Program Termination.
What I wanted to understand is why execution is falling through. Moreover, what does that error truly mean?
Here's the entire source code.
P.S. - This is my first time on Stack Overflow so if anything is undefined, hazy or plain ridiculous then please tell me.

My friend figured out what went wrong in the code. It turns out that pointer wasn't initialized to null and that caused a sort of cascading failure leading to the abnormal program termination error. Lesson learned.

Related

Access Violation when pressing a button that uses a separate form for validation [duplicate]

What tips can you share to help locate and fix access violations when writing applications in Delphi?
I believe access violations are usually caused by trying to access something in memory that has not yet been created such as an Object etc?
I find it hard to identify what triggers the access violations and then where to make the required changes to try and stop/fix them.
A example is a personal project I am working on now. I am storing in TTreeView Node.Data property some data for each node. Nodes can be multiple selected and exported (the export iterates through each selected node and saves specific data to a text file - the information saved to the text file is what is stored in the nodes.data). Files can also be imported into the Treeview (saving the contents of the text files into the node.data).
The issue in that example is if I import files into the Treeview and then export them, it works perfect. However if I add a node at runtime and export them I get:
"Access Violation at address 00405772 in module 'Project1.exe'. Read of address 00000388."
My thoughts on that must be the way I am assigning the data to created nodes, maybe differently to the way I assign it when they are imported, but it all looks ok to me. The access violation only shows up when exporting, and this never happens with imported files.
I am NOT looking for a fix to the above example, but mainly advice/tips how to find and fix such type of errors. I don't often get access violations, but when I do they are really hard to track down and fix.
So advice and tips would be very useful.
It means your code is accessing some part of the memory it isn't allowed to. That usually means you have a pointer or object reference pointing to the wrong memory. Maybe because it is not initialized or is already released.
Use a debugger, like Delphi. It will tell you on what line of code the AV occurred. From there figure out your problem by looking at the callstack and local variables etc. Sometimes it also helps if you compile with Debug DCUs.
If you don't have a debugger because it only happens on a client side, you might want to use MadExcept or JclDebug to log the exception with callstack and have it send to you. It gives you less details but might point you in the right direction.
There are some tools that might be able to find these kind of problems earlier by checking more aggressively. The FastMM memory manager has such options.
EDIT
"Access Violation at address 00405772
in module 'Project1.exe'. Read of
address 00000388."
So your problem results in a AV at addresss 00405772 in module 'Project1.exe'. The Delphi debugger will bring you to the right line of code (or use Find Error).
It is trying to read memory at address 00000388. That is pretty close to 00000000 (nil), so that would probably mean accessing some pointer/reference to an array or dynamic array that is nil. If it was an array of bytes, it would be item 388. Or it could be a field of a rather large object or record with lots of fields. The object or record pointer/reference would be nil.
I find that the really hard-to-find access violations don't always occur while I'm running in a debugger. Worse yet, they happen to customers and not to me. The accepted answer mentions this, but I really think it should be given more detail: MadExcept provides a stack traceback which gives me valuable context information and helps me see where the code fails, or has unhandled exceptions (it's not just for access violations). It even provides a way for customers to email you the bug reports right from inside your program. That leads to more access violations found and fixed, reported by your beta testers, or your users.
Secondly, I have noticed that compiler hints and warnings are in fact detecting for you, some of the common problems. Clean up hints and warnings and you might find many access violations and other subtle problems. Forgetting to declare your destructors properly, for example, can lead to a compiler warning, but to serious problems at runtime.
Thirdly, I've found tools like Pascal Analyzer from Peganza, and the audits-and-metrics feature in some editions of Delphi, can help you find areas of your code that have problems. As a single concrete example, Pascal Analyzer has found places where I forgot to do something important, that lead to a crash or access violation.
Fourth, you can hardly beat the technique of having another developer critique your code. You might feel a bit sheepish afterwards, but you're going to learn something, hopefully, and get better at doing what you're doing. Chances are, there is more way than one to use a tree view, and more way than one to do the work you're doing, and a better architecture, and a clean way of doing things is going to result in more reliable code that doesn't break each time you touch it. THere is not a finite list of rules to produce clean code, it is rather, a lifetime effort, and a matter of degrees. You'd be surprised how innocent looking code can be a hotbed of potential crashes, access violations, race conditions, freezes and deadlocks.
I would like to mention one more tool, that I use when other tools fail to detect AV. It's SafeMM (newer version). Once it pointed me to the small 5 line procedure. And I had to look more than 10 minutes at it, in order to see the AV that happened there. Probably that day my programming skills wasn't at their maximum, but you know, bad thing tend to happen exactly at such days.
Just want to mention other debugging or "code guard" techniques that were not mentioned in previous answers:
"Local" tools:
* Use FastMM in DebugMode - have it write zeros each time it dealocates memory. This will make your program PAINFULLY slow but you have a HUGE chance to find errors like trying to access a freed object.
* Use FreeAndNil(Obj) instead of Obj.Free. Some, people were complaining about it as creating problems but without actually providing a clear example where this might happen. Additionally, Emarcadero recently added the recommendation to use FreeAndNil in their manual (finally!).
* ALWAYS compile the application in Release and Debug mode. Make sure the Project Options are correctly set for debug mode. The DEFAULT settings for Debug mode are NOT correct/complete - at last not in Delphi XE7 and Tokyo. Maybe one day they will set the correct options for Debug mode. So, enable things like:
"Stack frames"
"Map file generation (detailed)"
"Range checking",
"Symbol reference info"
"Debug information"
"Overflow checking"
"Assertions"
"Debug DCUs"
Deactivate the "Compiler optimizations"!
3rd Party Tools:
Use MadShi or EurekaLog (I would recommend MadShi over EurekaLog)
Use Microsoft's ApplicationVerfier

Access violation, Delphi 2005 TADOQuery [duplicate]

What tips can you share to help locate and fix access violations when writing applications in Delphi?
I believe access violations are usually caused by trying to access something in memory that has not yet been created such as an Object etc?
I find it hard to identify what triggers the access violations and then where to make the required changes to try and stop/fix them.
A example is a personal project I am working on now. I am storing in TTreeView Node.Data property some data for each node. Nodes can be multiple selected and exported (the export iterates through each selected node and saves specific data to a text file - the information saved to the text file is what is stored in the nodes.data). Files can also be imported into the Treeview (saving the contents of the text files into the node.data).
The issue in that example is if I import files into the Treeview and then export them, it works perfect. However if I add a node at runtime and export them I get:
"Access Violation at address 00405772 in module 'Project1.exe'. Read of address 00000388."
My thoughts on that must be the way I am assigning the data to created nodes, maybe differently to the way I assign it when they are imported, but it all looks ok to me. The access violation only shows up when exporting, and this never happens with imported files.
I am NOT looking for a fix to the above example, but mainly advice/tips how to find and fix such type of errors. I don't often get access violations, but when I do they are really hard to track down and fix.
So advice and tips would be very useful.
It means your code is accessing some part of the memory it isn't allowed to. That usually means you have a pointer or object reference pointing to the wrong memory. Maybe because it is not initialized or is already released.
Use a debugger, like Delphi. It will tell you on what line of code the AV occurred. From there figure out your problem by looking at the callstack and local variables etc. Sometimes it also helps if you compile with Debug DCUs.
If you don't have a debugger because it only happens on a client side, you might want to use MadExcept or JclDebug to log the exception with callstack and have it send to you. It gives you less details but might point you in the right direction.
There are some tools that might be able to find these kind of problems earlier by checking more aggressively. The FastMM memory manager has such options.
EDIT
"Access Violation at address 00405772
in module 'Project1.exe'. Read of
address 00000388."
So your problem results in a AV at addresss 00405772 in module 'Project1.exe'. The Delphi debugger will bring you to the right line of code (or use Find Error).
It is trying to read memory at address 00000388. That is pretty close to 00000000 (nil), so that would probably mean accessing some pointer/reference to an array or dynamic array that is nil. If it was an array of bytes, it would be item 388. Or it could be a field of a rather large object or record with lots of fields. The object or record pointer/reference would be nil.
I find that the really hard-to-find access violations don't always occur while I'm running in a debugger. Worse yet, they happen to customers and not to me. The accepted answer mentions this, but I really think it should be given more detail: MadExcept provides a stack traceback which gives me valuable context information and helps me see where the code fails, or has unhandled exceptions (it's not just for access violations). It even provides a way for customers to email you the bug reports right from inside your program. That leads to more access violations found and fixed, reported by your beta testers, or your users.
Secondly, I have noticed that compiler hints and warnings are in fact detecting for you, some of the common problems. Clean up hints and warnings and you might find many access violations and other subtle problems. Forgetting to declare your destructors properly, for example, can lead to a compiler warning, but to serious problems at runtime.
Thirdly, I've found tools like Pascal Analyzer from Peganza, and the audits-and-metrics feature in some editions of Delphi, can help you find areas of your code that have problems. As a single concrete example, Pascal Analyzer has found places where I forgot to do something important, that lead to a crash or access violation.
Fourth, you can hardly beat the technique of having another developer critique your code. You might feel a bit sheepish afterwards, but you're going to learn something, hopefully, and get better at doing what you're doing. Chances are, there is more way than one to use a tree view, and more way than one to do the work you're doing, and a better architecture, and a clean way of doing things is going to result in more reliable code that doesn't break each time you touch it. THere is not a finite list of rules to produce clean code, it is rather, a lifetime effort, and a matter of degrees. You'd be surprised how innocent looking code can be a hotbed of potential crashes, access violations, race conditions, freezes and deadlocks.
I would like to mention one more tool, that I use when other tools fail to detect AV. It's SafeMM (newer version). Once it pointed me to the small 5 line procedure. And I had to look more than 10 minutes at it, in order to see the AV that happened there. Probably that day my programming skills wasn't at their maximum, but you know, bad thing tend to happen exactly at such days.
Just want to mention other debugging or "code guard" techniques that were not mentioned in previous answers:
"Local" tools:
* Use FastMM in DebugMode - have it write zeros each time it dealocates memory. This will make your program PAINFULLY slow but you have a HUGE chance to find errors like trying to access a freed object.
* Use FreeAndNil(Obj) instead of Obj.Free. Some, people were complaining about it as creating problems but without actually providing a clear example where this might happen. Additionally, Emarcadero recently added the recommendation to use FreeAndNil in their manual (finally!).
* ALWAYS compile the application in Release and Debug mode. Make sure the Project Options are correctly set for debug mode. The DEFAULT settings for Debug mode are NOT correct/complete - at last not in Delphi XE7 and Tokyo. Maybe one day they will set the correct options for Debug mode. So, enable things like:
"Stack frames"
"Map file generation (detailed)"
"Range checking",
"Symbol reference info"
"Debug information"
"Overflow checking"
"Assertions"
"Debug DCUs"
Deactivate the "Compiler optimizations"!
3rd Party Tools:
Use MadShi or EurekaLog (I would recommend MadShi over EurekaLog)
Use Microsoft's ApplicationVerfier

What can cause CICS transaction to write out of CICS allocated memory?

I'm using CICS in Cobol program and I've noticed that sometimes data are written out of the CICS memory. It cause a data corruption and my application stop. I don't know where it append, so I'm creating a parser to analyse my Cobol code to look for possible corruption in COMMAREA used by CICS. Now I checked following statements :
EXEC CICS XCTL
EXEC CICS LINK
EXEC CICS RETURN TRANSID
For each, I check if sent length (declared in LENGTH parameter) is not greater than sent COMMAREA. Then I check if DFHCOMMAREA, in the receiving program is not greater than sent COMMAREA (according to this doc http://publib.boulder.ibm.com/infocenter/cicsts/v3r1/index.jsp?topic=%2Fcom.ibm.cics.ts31.doc%2Fdfhp3%2Fdfhp37t.htm) :
The receiving data area need not be of the same length as the original communication area; if access is required only to the first part of the data, the new data area can be shorter. However, it must not be longer than the length of the communication area being passed. If it is, your transaction may inadvertently attempt to read data outside the area that has been passed. It may also overwrite data outside the area, which could cause CICS to abend.
Now, I'm wondering what other things should I parse in order to detect memory overwritting?
As you are using Micro Focus COBOL, you could set the memory_strategy tunable (or the CBL_MEM_STRATEGY API) to help you analysis where the error is occurring by allowing the runtime to protect memory in various different ways.
Memory can also be validate via the "CBL_MEM_VALIDATE" call.
Another thing can do is use the tracing support... lookup CTF (Consolidated Tracing Facility). This will give you an idea where you code is at the time of the error.
Some References that will help you;
http://kb.microfocus.com/display/4/kb/article.aspx?aid=31645
http://documentation.microfocus.com/help/index.jsp?topic=%2Fcom.microfocus.eclipse.infocenter.studee60win.sp02ws01%2FHRRTRHRTCF0O.html
http://documentation.microfocus.com/help/index.jsp?topic=%2Fcom.microfocus.eclipse.infocenter.studee60ux.sp02ws01%2FGUID-762085AC-8396-4D71-9CC1-6231551D3AEE.html
For the passing-of-data bounds checking, always use transclusion, which in COBOL is called a COPYCODE or COPYBOOK. Pass the root data element in the copycode, and compile the same version in the caller and called program. This COPYCODE is sortof the contract for the called program, so it is a good idea to have a naming convention tying them together. To make sure they are in-sync, whenever you change the COPYCODE, recompile all programs that reference it.
Also, the use of SSRANGE is great (but someone already mentioned that).
NealB has a good idea. I suggest you also look into the STGPROT and RENTPGM CICS system initialization parameters.
When a CICS program starts writing all over memory it will not only "stop working" but possibly
crash the CICS region as well!
If you are sure that the LENGTH is set properly on LINKs and XCTLs and that you are
receiving the COMMAREA into a linkage record of that size (EIBCALEN), then you should
be fine.
Rather than trying to parse your COBOL programs I suggest that you set compiler
bounds checking options on. The problem you are having is most likely related to
indexing or subscripting beyond the bounds of a working storage table. Attempting to detect
this class of programming error through static analysis is generally not very
effective.
Setting bounds
checking on should detect out of range memory references, issue a diagnostic message to
the log, and then and terminate your program
before it crashes the whole CICS region. The logged message should point you the the
source line where the out of bounds reference occured.
Check out the SSRANGE compile time option. Make sure it is set and that your CICS region
runs LE enabled programs with CHECK(ON).
This should nail out of bounds memory
references pretty quickly.

How do I debug an Access violation in the field?

An application in the field is getting this message intermittently:
I am not able to reproduce this on my machine. I have also traced what I believe is the relevant code and can't find any access to uninitialized objects.
I've never had to deal with this kind of problem.
I did a build with madExcept and unfortunately the program does not crash once it is bundled.
Any opinions on madExcept vs EurekaLog for finding this kind of thing? I've never used FastMM. Would it be useful in his situation? (Delphi 2010) Any suggested flags to set in FastMM? Any other recommendations?
Note the very low address you are attempting to read. This sort of error almost certainly means you attempted to dereference a nil pointer even if you can't find one.
Given your description of the behavior I would suspect you've got a memory stomp going on--something is blasting a zero on top of the pointer to an object. When you change things you move things around and the stomp moves to someplace harmless.
Turn on both range checking and overflow checking.
Note the offending object must be at least 3C0 bytes in size--this should help narrow it down, most objects will be smaller than this.
What I have done in the past with such errors that only show in the field is put logging checkpoints in--a bunch of lines that display something in an out of the way place--a simple sequence of numbers is fine. Find out what number is showing when it crashes and you know which of you checkpoints was the last to execute. If that doesn't narrow it down enough you can repeat the process now that you've narrowed it down.
With a full map file you can identify the exact point in the code where this occurs. I hope you have a full map file for this image! Subtract $00401000 from the address at which the exception is raised ($007ADE8B in your case) and that corresponds to the values in the map file.
Having done that you know which object is nil and from there it is usually not too hard to work out what is going on.
One of the most common ways for this to occur is when a constructor raises an exception. When this occurs the destructor runs. If you access, in a destructor, a field that has not been initialised, and do anything other than call Free on it, then you will get an exception like this.
Looks like a memory overwrite where changing memory layout (your machine vs field machine or adding madExcept) makes the overwrite change something harmless.
FastMM is great at of making this kind of problems happen more consistently (and finding their source). Download the full version of FastMM, add it as the first unit of your project, and turn on FullDebugMode on its settings.
It might cause the problem to be reproduceable in your machine right away. If not, don't forget to deploy FastMM_FullDebugMode.dll with your application for testing. Keep madExcept on and let it embed the .map file for call stacks.

Delphi 7 exception not caught

I have some really complicated legacy code I've been working on that crashes when collecting big chunks of data. I've been unable to find the exact reason for the crashes and am trying different ways to solve it or at least recover nicely. The last thing I did was enclose the crashing code in a
try
...
except
cleanup();
end;
just to make it behave. But the cleanup never gets done. Under what circumstances does an exception not get caught? This might be due to some memory overflow or something since the app is collecting quite a bit of data.
Oh and the exception I got before adding the try was "Access violation" (what else?) and the CPU window points to very low addresses. Any ideas or pointers would be much appreciated!
"Very low address" probably means that somebody tried to call a virtual method on an object that was not really there (i.e. was 'nil'). For example:
TStringList(nil).Clear;
The first part is very mysterious, though. I have no idea how that can happen.
I think you should try to catch that exception with madExcept. It has never failed me yet. (Disclaimer: I am not using D7.)
A trashed stack or a stack overflow can both cause irreparable harm to the structures on the stack that structured exception handling (SEH) in Windows uses to find the actual exception handlers.
If you have a buffer overflow in a buffer on the stack (e.g. a static array as a local variable but written beyond its end), and overwrite an exception record, then you can overwrite the "next" pointer, which points at the next exception record on the stack. If the pointer gets clobbered, there's nothing the OS can do to find the next exception handler and eventually reach your catch-all one.
Stack overflows are different: they can prevent calling functions at all, since every function call requires at least one dword of stack space for the return address.
you have a number of good answers. the wildest problems i've had to chase come from stack corruption issues like barry mentioned. i've seen stuff happen with the project's "Memory sizes" section on the linker page. i might be superstitious but it seemed like larger wasn't necessarily better. you might consider using the enhanced memory manager FastMM4--it's free & very helpful.
http://sourceforge.net/projects/fastmm/
i've used it with d7 and found some access to stale pointers and other evil things.
you may also wish to create a way to track valid objects and or instrument the code in other ways to have the code checking itself as it works.
when i'm seeing access to addresses like 0x00001000 or less, i think of access to a nil pointer. myStringList:=nil; myStringList.Clear;
when i'm seeing access to other addresses with much larger numbers, i think of stale pointers.
when things are strangely unstable & stack traces are proving to be nonsense and/or wildly varying, i know i have stack issues. one time it's in Controls.pas; next time it's in mmsys.pas, etc.
using the wrong calling convention to a DLL can really mess up your stack as well. this is because of the parameter passing/releasing when calling/returning from the DLL.
MadExcept will be helpful in finding the source of this, even if it shows nonsense...you'll win either way because you'll know where the problem is occurring or you'll know you have a stack issue.
is there any testing framework you can put on it to exercise it? i've found that to be very powerful because it makes it entirely repeatable.
i've fixed some pretty ugly problems this way.
I'll leave the reasons why the except might not work to Barry...
But I strongly suggest a simple strategy to narrow down the area where it happens.
Cut the big chunk in smaller parts surrounded by
try
OutputDebugString('entering part abc');
... // part abc code here
except
OutputDebugString('horror in part abc');
raise;
end;
...
try
OutputDebugString('entering in part xyz');
... // part xyz code here
except
OutputDebugString('horror in part xyz');
raise;
end;
and run your code with DebugView on the side... (works for apps without GUI as well like services).
You'll see which part is executed and if the exceptions are caught there.
I used to get this strange behabiour when calling some COM object that used a safecall calling convention. This object/method may raise an EOleException, not trapped by the usual try/except on the client code.
You should trap an EOleException and the handle it properly.
try
...
except
on E: EOleException do
...
end;
I don't know if it is the problem you are facing. But if it is, i recommend you to take a look at Implement error handling correctly, a very clarifiyng post about exception handling in delphi.
You can also enable your IDE Debug Options to stop on delhi exceptions e monitor the stack trace.
Is this perhaps a DLL or a COM object? If so, it is possible that the FPUExcpetion mask is being set by the host application to something different than Delphi is used to. An overflow, by default in Delphi produces an exception, but the FPUExcpetionmask can be set so that it doesn't, and the value is set to NAN. See the math.pas unit for more information on FPUExceptionmask
I've gotten exceptions in the initialization and finalization blocks of my code which madExcept doesn't even seem to even catch. This might occur if you're referencing external DLL's inside of that try block. I'm not certain of the reason.
Actually (and thanks to #Gung for informing me of the worthlessness of my ancient answer), I read this recently in the ancient O'Reilly Delphi Tome. You should put SysUtils as the first (or second after your non-standard memory manager unit) in your main form's DPR so that it's resident in memory with all it's Exception Catching goodness. Otherwise, if it's loaded from some other unit, it will be unloaded with that unit too and you can kiss built in exception handling goodbye.

Resources