You can debug Realsoft 3D plugins and applications using your favourite debugger. Just build your plugin with debug information.
On Windows you get debug versions simply by entering r3make. To get optimized version build with 'r3make NODEBUG=1'.
On unix based systems, pass -debug startup parameter to the startup script. For example:
. ./setenv.linux -debug
There is a special Realsoft 3D Debug version available for plug-in developers. The debug version contains several debugging systems, which help you to find bugs from your code.
It is highly recommeded that You test your plug-ins with the Realsoft 3D Debug version before releasing your product.
![]() |
Note |
---|---|
You can use the debug libraries provided that you use R3Alloc(), R3Free() and R3ReAlloc() functions for all memory managment. Many of the debugging systems count on these functions. They allocate extra memory below and beyond the actual data chunk passed to the caller and initialize the memory so that various program errors can be detected. Many of the debugging systems depend on these functions. |
1. Windows: Make sure the SDK version you are using includes the debug versions of the link libraries (the folder 'sdk\debuglib'). The debug link libraries are included with the SDK release 04.26.40 or newer.
2. Download and install the debug version from the Realsoft3D SDK site.
![]() |
Note |
---|---|
Both the release and debug version of Realsoft 3D can be installed and run on a single workstation. However, the two versions are not binary compatible. You must install the debug version into a new fresh folder and you cannot mix the binaries of the two. Trying to use a debug plugin in a release version or vise versa will crash. |
3. Edit the appropriate setup script in sdk/scripts folder so that it refers to Realsoft 3D Debug version rather than the official Realsoft 3D release version. Also, define the environment variable R3DEBUG=1. The definition should already be there in the setup scripts, so you just need to uncomment it.
1. Recompile all your plug-ins. Make sure the compiler output includes the definition R3DEBUG=1, which verifies that you are really building a debug version rather than a release version. Mixing release and debug versions will crash the program.
2. Start Realsoft 3D Debug version and use the program as usual, to test your plug-ins. If the debug version detects any problems with your code the problem report is written 'logs/realsoft3d debug.log' file.
![]() |
Note |
---|---|
Some of the detected problems may be rather fatal in which case the debug systems deliberately cause the program to crash immediately. Some of the bugs are less fatal and they are silently written to the program log file. Always remember to study the contents of the application log file after you have exited the program. |
If your plugin generates error messages, such as Undefined Method or Undfined Attribute errors, you can debug these out by setting a break point to R3_Error function. When the break point is hit, then study the call stack in the debugger to see from which part of your plugin the call is made.
Memory overwrite bugs are often tricky to find. The program may crash once a day here and there. Debug version detects all overwrites and reports them to the program log file. The debug version finds over and underwrites for you and reports them with the following message:
Overwrite. Alloced in ..., Freed in ... Clid? = (class id)
The error message tells the source file and line from which the memory allocation and release calls were made. If the memory was allocated for Realsoft3D objects, the Clid specifies the class id of the object.
Sometimes overwrite may be very fatal in which case the program just crashes instantly without a change to call R3Free(). You can find the cause by adding extra R3CheckOverWrites() calls to your code. If the call detects overwrites, the program is deliberately crashed to a invalid memory reference.
Another common bug is that program refers to a memory which was already freed. Again, these errors may be hard to find. If the reference to a freed memory happens soon after the memory was deallocated, the operating system may not have assigned the memory to another process and the reference doesn't generate immediate crash. However, in heavy multi tasking situtations, the program crashes at some random position, which usually doesn't have anything to do with the actual bug.
This kind of bugs are also easy to track with the debug version. R3Free() keeps track of allocated and freed memory and initialized the memory so that any references to freed memory will generate page fault and lead to a crash. You can also detect whether a memory is freed or not by viewing it in the debugger. All the freed memory is initialized to 0xae.
Attemps to free memory chunck twice will also be detected. The following error message is written to the program log file:
Mem freed twice. Alloced in (source file) at (line). First free in (source file) at (line). Also freed in (source file) at (line).
Attempting to free memory that was never allocated will generate the following error message.
Free called for memory not alloced or bad overwrite. Freed in __FILE__ at __LINE__.
Attempting to call R3Free() with wrong size will crash the program and generate the following error message to the program log file:
Memory freed with wrong size. Alloced in __FILE__ at __LINE__. Freed in __FILE__ at __LINE__. Clid? = classid
When the program exits, all memory leaks are dumped into the program log file. Error messages look as follows:
Not freed (address). Allocated in __FILE__ at __LINE__. Size (bytes). Clid/name = (clid)/(name). Refcount? = (reference count). str=(string).
Note: Clid/name/refcount specifies the object's classid, name and reference count. These make sense only if the memory was allocated for an object.
If the memory seems to hold a string, the string is dumped to the log file as well.
Debug version will detect several reference counting related bugs.
If you are using reference counting for managing an object, you must not delete objects explicitely. Object will get automatically deleted when the reference count attribute drops to zero, in other words, when nobody needs the object anymore.
Correspondingly, all direct R3RM_DELETE calls to reference counting managed objects will generate the error message:
DELETE: refcount == (refcount)
implying that someone is still using the object you are trying to explicitely delete.
Another common reference counting bug is that an object whose reference count just dropped to zero and has therefore got its R3RM_DELETE method, calls R3RM_REF, directly or indirectly. You should not call R3RM_REF from R3RM_DELETE method and the debug version shows you the following error:
R3RM_REF called from R3RM_DELETE
The debug version detects all attemps to use deleted objects. This is done so that method calls are not dispatched to the object dispatcher function directly. Instead, method calls are dispatched to a function which runs various tests to make sure the object to be called is valid. If not, the following error message is written to the log file and the program is terminated.
SendMsg() to deleted object mth=(method), File: __FILE__, Line:__LINE__
If you attemp to send a message to an address which doesn't point to a Realsoft 3D object, one of the following error messages is shown:
SendMsg() to address 0. mth = (method id) Illegal class id (id). mth=(method id)
If you attemp to create an object whose class is not registered, the following error message is shown.
Class (classid) not installed. Mth=(methodid)
If an object doesn't recognize the given method / attribute, it reports the method / attribute identifier to the log file with the following error message:
Undefined attribute (class id, attribute id)
For example, attempting to set a sphere attribute to a nurbs mesh:
R3SetAttrs(nurbs, R3SPHA_Radius, ..
will generate error message:
Undefined attribute (classid, attributeid)
implying that the class 'classid' doesn't recognize the attribute 'attributeid'.
Model-view system connects the user interface to the functionality layer. The debug version helps you to find several model-view related problems.
Non-detached models
When you attach a model to a gadget (say, in your r3rm_create method), you must also take care of detaching model from the gadget in th r3rm_delete method.
If you fail to do this the gadget won't be able to die because the model keeps it alive via reference counting system.
The debug version attemps to detect these situations so that when a window is deleted it studies whether the children have been detached from their models. If not, the following error message is shown:
WARNING: Widget 'Property Window' (cl=window's class id) is removing its child '' (cl=childs clid) whose R3WGA_Model attribute still points to model 'Geometrics' (cl=model's class id).
Another warning that may indicate a bug in your code is:
WARNING: Widget 'Property Window' (20) is removing a child '' (1280) with suspiciously high reference count (ref=5).
When a window is destroyed, it will unref all its children so that they can die as well. The window should have also detached the children from their models before this. So high reference counting value may indicate that there are still many other objects that refer to the children in question. This may not be a bug (there may just be pending refresh events in the window's queue explaining the high reference count value) but its something you should pay attention to.
Multi threading problems
The user interface code can be executed only by the main thread. This restriction is mainly due to operating systems specific reasons. Correspondingly, the debug version will report all attemps to call R3MM_ADDEPENDENT from other than the main thread will generate an error message.
ONLY THE MAIN THREAD CAN DO ADD DEPEND
Note: in theory two model objects could be linked with each other using model-view concept, in which case the debug version incorrectly reports it as a bug.
Adding models multiple times
If you implement user interface classes that support model-view concept, you handle the model attributes by calling R3MM_ADDEPENDENT method.
Calling the method several times per view doesn't really make any sense so the debug version generates:
View attached to a model multiple times
error.
The Windows menu includes a special debugging window called 'Instance Monitor'. You should use this window to make sure all the resources allocated by your user interface objects are also released properly when the corresponding window is closed.
A typical user interface bug is that you set a model to a view (an user interface object) but you never detach it from the model and the view is not able to die.
When the program is exited, all models will be deleted, and also the views will then die and therefore these leaks will newer show up at the program log file. Therefore it is important that you use the Instance Monitor to make sure all the resources gets released when the window using your controls is closed.
You must delete all objects you create. If you don't, debugging libraries report the classes and names of objects not deleted.
Class 'classid' : 'n' instances not deleted.
User interface objects connect to the model objects by calling R3MM_ADDDEPENDENT method. Correspondingly, when a window is closed it should call R3MM_REMOVEDEPENDENT. The debug version gives and error message if the model does not recognize the object to be removed.
R3MM_REMOVEDEPENDENT: found 0 dependants
You can enable heavier debug tests by passing -debug startup parameter to the program. When given, the program will make sure that every method call gets dispatched to a valid object. It does this by keeping track of every created object and by making sure the called object is in the list of created objects.
Needles to say, doing this per method call is very time consuming and slows down the program execution a lot.
Some of the debugging systems slow down with the number of instances or allocated chunks and the debug version runs significantly slower compared to the release version.