Issues & workarounds

From Team Developer SqlWindows Wiki
Jump to: navigation, search

Dynalib issues & workarounds


Pointer2.png Issue : case sensitive dynalib filenames Pointer.png

Defect ID : TD-345

When the application uses several dynalibs which are included at several levels
(so dynalibs include each other and use several different entry points) these symptoms could emerge :

  • Initialised dynalibs seems to loose their data
  • Windows are created multiple times, but logically they should not
  • Dynalibs can not find their own qualified references
  • Code which should be executed once (e.g. at initialisation or closing) are called multiple times

This bug seems to be present in all TD versions.

Normally, the way include items are declared does not matter.
If you include a normal library using Base.apl or BASE.apl, Team Developer treats them equally.

But there is a bug how TD treats including Dynalibs at runtime.
Seems Dynalib1.apd is not the same as DYNALIB1.apd (mind the case difference).
At runtime, TD loads the dynalib multiple times when the dynalib is included at several levels with
different case in the filename. A dynalib should be loaded only once in the system !
TD thinks the dynalibs are not the same. This results in multiple runtime instances of the same dynalib.


Check your complete application structure and be sure all dynalibs are included with the same case for the filename.
See picture for a visual explanation. The red include line is wrong. Dynalib2.apd includes Dynalib1.apd using a different
case for the filename compared to the Executable.

At runtime Dynalib1.apd is loaded twice. So when the executable has initialized its own instance of Dynalib1.apd
(the dynalib has loaded some data and holds it), Dynalib2.apd expects an initialized dynalib. But in fact Dynalib2.apd
has its own instance which will be initialized again.

So it is not the case of the filename itself (the physical filename on disc), but the way the dynalib name is spelled in the include section of your sources.

Pointer2.png Issue : application crashes when it closes Pointer.png

The application crashes during close generating a GPF or memory read/write error.

This bug seems to be present in all TD versions.

When the application uses several dynalibs which contain classes with class variables and they are used
by more than one dynalib in the system, TD could release the memory wrongly.
Every dynalib should be totally shielded from other dynalibs as a blackbox. Classes within a dynalib
can not be exported and should not be available to the outside. But TD at runtime seems to get confused when
multiple dynalibs declare the same classname with class variables. When TD releases the memory, it releases
it twice or releases the wrong memory size. This will get TD to crash at close.

Check your complete application structure and be sure all dynalibs are using unique classnames OR be sure
that when you declare classes with the same names spread over dynalibs, they are identical in structure.
So the sequence and contents of the class attributes should be equal.
Another workaround is to manually set all UDV's involved to NULL in the dynalibs just before closing the application.

Pointer2.png Issue : SalCompileAndEvaluate: the performance of the build varies between each build of the dynalib Pointer.png

Defect ID : 83056

Calling SalCompileAndEvaluate in a dynalib seems to get very slow depending of the dynalib build.
The performance could be a few percentages slower or in worse cases could take minutes for one call.
During execution the CPU of the PC is getting to 100% which locks the PC and a hard reset could be the
only way to stop the application.

This bug seems to be present in TD3.x
It is solved in TD42 (fixed defect ID 83056, see notes on TD42 fixes).

Seems the symbol table of the dynalib is messing up the total symbol table of the application
which causes the slowdown.

A simple workaround is to force the application to freshen up the symbol table of the main executable
which will totally solve the performance issues.
To do this, the main executable should call a SalCompileAndEvaluate at startup. It does not matter
which actions are performed in the call. When the main application executes the command, all injected
dynalibs which uses SalCompileAndEvaluate will work in full speed.

Here a sample of a dummy call

Function: PALForceDynalibIntegrity
   Local variables
      String: saTest[*]
      Number: nError
      Number: nDummy
      Number: nCount
      String: sDummy
      Date/Time: dtDummy
      Window Handle: hWndDummy
      Set nCount = 0
      While nCount < 5
         Call SalCompileAndEvaluate( "Set saTest[" || SalNumberToStrX( nCount, 0 ) || "] = '" || SalNumberToStrX( nCount, 0 ) 
         || "'",    nError, nDummy, nDummy, sDummy, dtDummy, hWndDummy, FALSE, SalContextCurrent(  ) )
         Set nCount = nCount + 1

Now call the function at application startup (in main executable) :

Application Actions
   On SAM_AppStartup
      Call PALForceDynalibIntegrity( )

Here you can download the sourcecode for the function:

Pointer2.png Issue : Formats/input masks do not work on dynalib top level windows Pointer.png

When using top level windows (forms, dialog boxes etc) from dynalibs, formats/input masks defined on fields within the dynalib top level windows do not work.
When trying to enter data into the fields, these issues could emerge :

  • All data can be entered, the formats and input masks seem not to be present
  • Data can not be entered, the field seems to be locked
  • A GPF occurs when entering data into the field

When the list of formats/input masks in the main application differs from those defined in the dynalib, TD seems not to make the dynalib formats available
to the main application. So the main application only uses the formats/input masks defined within the main source only.

You need to make the dynalib(s) formats section equal to the main application formats section.
Copy all needed formats from the dynalib and place them into the formats section of the main application.
Also the sequence of formats is important. So it is best to copy/paste the complete section.

Here you can download a sample:

Pointer2.png Locate dynalib issues using DynalibChecker Pointer.png

New version 1.1 available.
- Much faster operation
- Workaround for CDK memory leak bug
- Now in TD 1.5.1 source format (TD 1.x) and TD4.2 (and higher, also TD60 WIN32)

It is wise to check your sources for the issues described in this section to be sure you won't get strange behavior.
Correcting them accordingly will result in a more stable system.

Since I began using dynalibs I discovered these issues along the way, but it is a hard task
to check for them when the application gets bigger.
But it is needed, because when the workarounds are applied, a system utilizing dynalibs is highly stable.

On one application which uses more than 70 dynalibs, I decided to create a CDK tool to automate checking the sources.
It is used regularly and finds the issues quickly and gives a more precise way to pinpoint the faulty locations.

So here I post the tool, named Dynalib Checker, for public use.
It is an application using CDK. The source is included.

A readme textfile is included in the archive with more info.

Here the download link for the tool:

DynalibChecker Classes.gif