Smalltalk Programming Language : Q: How do I determine whether my Smalltalk memory is corrupted?

Q: How do I determine whether my Smalltalk memory is corrupted?
A: If your application suddenly terminates, it may be because it has accessed corrupted memory. Use verification methods to determine whether Smalltalk memory is corrupted.
Smalltalk Memory Verification
Introduction
When Smalltalk memory gets corrupted, the resulting failure can be sudden and leave few traces. Sometimes the failure is so catastrophic that no log file can be generated. When log files are generated, they often only allow the developer to confirm that the memory being accessed has no meaningful information. The culprit is long gone and tracking it down is difficult.
This article identifies Smalltalk methods which can help locate memory corruption and outlines strategies for isolating the code causing the memory corruption.
The Usual Suspect
The most likely place for Smalltalk memory to get corrupted is during calls to external functions. Real world applications make these calls in many places:
Plan of Attack
When Smalltalk memory corruption is suspected, the developer can request a verification of Smalltalk memory by invoking one of three public instance methods for Object. These methods trigger the examination of Smalltalk memory and return whether and where Smalltalk memory is corrupted. They are part of the base image. The three public instance methods for Object are
These methods may be time-consuming to run and so are not suitable for use in production environments.
Basic Usage
All three verification methods output information to the TTY transcript. You must start your image with the '-l<log filename>' option in order to collect the information.
Successful (i.e. non-corrupt memory) output will look like:
{VI:}
 
and corrupt image output will have information about the segment and pointers involved. Here is an example of corrupt image output:
 
{VI:
Object in segment 17cda0 is not remembered 2ccffdec (Automatic remember
performed)
......
Verify Memory Segment: Old space:: Memory Space base 2b20020 alloc 2efabf0}
Object>>verifyImage is the most general call. It will walk all of memory, process stacks and internal VM structures. This can take a lot of time so this routine should be used to narrow down the area in which to search for the problem. A 100 Mhz Pentium will execute the verifyImage in about 6 seconds. A verifyImage call will include a call to verifyMemorySpaces and verifyVMSlots. This is the call to use for random crashes.
Object>>verifyMemorySpaces walks all of object memory to determine object memory is valid. This call skips the internal structures. This call can be used to determine if object memory is being written into. This call can run slightly faster but still takes about 5 seconds on a 100 Mhz Pentium. This is the call to use for random crashes where the process of examining Smalltalk memory with verifyImage itself crashes.
Object>>verifyVMSlots verifies the process stacks, and internal VM structures and internal VM structures, so it is faster. This call runs in about 2 ms on a 100 Mhz Pentium. This is the call to use if you suspect that the return value form a primitive is invalid or a primitive call is corrupting memory.
Strategies of Pursuit
If you are getting errors due to corrupted memory, you can add calls to the image verification routines to determine the culprit. If you have no idea what is causing the problem, you can add a periodic call based on a timer. For example:
[
[true] whileTrue: [
TranscriptTTY default cr; nextPutAll: Time now printString; nextPutAll: ' Image verification'; cr.
self verifyImage.
(Delay forSeconds: 60) wait]] forkAt: Processor userBackgroundPriority.
Sometimes a developer familiar with the structure of an application can pinpoint which external calls are likely based on what the application was doing when the crash occurred. If this is the case, the developer can fence the suspect code with calls to verify Smalltalk memory as per the example of basic usage.
TranscriptTTY default cr; show: 'Verify before call'; cr.
self verifylmage.
TranscriptTTY default cr; show: 'Make the call'; cr.
self do the call . . .
self verifylmage.
Check the log file for errors after a crash. Note: The verify image code is slow as it walks all of memory. It is best to place the verification code only in places suspected of causing corruption to reduce performance problems. Also, verifyMemorySpaces or verifyVMSlots can be used. The former if verifyImages crashes and the latter if you suspect that the return value from a primitive is invalid or a primitive call is corrupting memory. This call can be used to verify that the Smalltalk stack contains valid or invalid objects.