Hallvard's Blog

Tuesday, June 10, 2014

So much time could be saved if everyone followed these simple steps when reporting issues:

1. What did you do? (the dreaded steps)
2. What happened? (screenshots, logs etc are useful here)
3. What did you expect to happen?

Steps are crucial to try and reproduce the problem.

Describing what actually happened and contrasting it with what you expected to happen is essential to decide what you saw was a bug, a misunderstanding or something else entirely :).

A simple example:

"Market window: Cannot sort on the Time column
1. Start the application with an empty workspace
2. Press Ctrl+M and type SSE<Enter> to open a market window
3. Double-click on the Time column
exp: The market data should be realtime-sorted on the changing Time column
act: Nothing happens, stock list stays in market segment/alphabetical order
<attached: screenshot>"

Friday, November 04, 2011

As you may have noticed (or not :), this Blog has been silent since 2008. Several people have asked me recently why I'm not blogging anymore - here is a short explanation.

I was blogging quite actively for a while, but other priorities in my life (family, work, new house, exercising etc) have taken over. There is only so much time.

While I've been silent on the blog for a few years now, I'm still programming in Delphi professionally and I follow the community closely. At work, we have until now decided to stay with Delphi 2007, and I've been lagging behind on digging down into the low-level technical details of newest versions and features.

So there has been less to blog about. Now we're in the process of upgrading to XE2 - and there are regularly issues and points of interest that might spark my interest into blogging again - we'll see....

Also there are many, really good Delphi blogs now - I see less "holes" that needs to be discussed. If I blog, I don't want to blog about topics that others cover well, anyway :-).

Sunday, March 30, 2008

"The Delphi linker has always had the option of including so-called Turbo Debugger (TD32) debug information (on the Linker page of the Project Options dialog). The internal IDE Debugger does not normally use this information (Delphi 4 and 5 uses it when debugging external DLLs and EXE files), but instead relies on internal compiler structures build during an interactive compile.

External tools such as Borland’s Turbo Debugger[i] does rely on the TD32 information tacked at the end of the EXE or DLL file to enable symbolic debugging. This information is also used by a number of third party tools such as Numega’s BoundsChecker[ii], Turbo Power’s suite of Sleuth QA[iii] tools, Atanas Stoyanov’s freeware MemProof memory checking tool[iv], AutomatedQA’s QTime profiler[v], and Intel’s VTune sampling profiler [vi]

In this article we will see how we can utilise a relatively new DLL from Borland, BorDebug.DLL, to read and interpret the TD32 debug information in our own applications. [...]

We will discuss the functionality provided by the BorDebug DLL, present an import unit that gives us access to it from our Delphi applications, look at a set of wrapper classes to simplify the usage and show some simple demonstration programs."

H. Vassbotn, TDM, November 2000

unit HVBorDebug;{ Simplified class interface for the BorDebug API Written by Hallvard Vassbotn (hallvard.vassbotn@c2i.net), April 1999 - September 2000

Saturday, March 15, 2008

One of the key questions you should ask yourself as a serious Delphi developer is; what kind of exception handling and logging am I using. If you're not using any custom or third party solution for tracking down exceptional incidents that occur in your production systems or at your customer sites, you're missing out big time!

A proper exception handling and logging system should at least log the calling context (the calls that lead up to the exception) in the form of a stack trace. This makes it so much easier to track down, identify and fix the cause of the problem.

In 1999 I wrote such a tool and published it in The Delphi Magazine article Exceptional Stack Tracing in October 1999. As I have mentioned before, parts of this tool is based on my earlier work on 16-bit stack tracer, YAST. It also uses the excellent RTLI (run-time line information) tool by Vitaly Miryanov. At the time I was inspired by Per Larsen's ExHook32 and Stefan Hoffmeister's Debug Mapper. So I upgraded and improved the stack tracer for Win32, integrated the RTLI code and researched and developed a general implicit DLL import hooking system and a specific exception notification mechanism.

Putting all the pieces together we were able to get meaningful symbolic stack traces from any exceptional error incident - wether it happened during development, testing or at the customer's site. This made it an order of magnitude easier and faster to identify and fix bugs that caused the exception (or to handle it more gracefully).

I always spent a fair amount of time on my articles, but this one was by far the most time-consuming. Here are some key excerpts from the article.

"Often, during beta testing of an application (and, horrors, sometimes in a release version), users will encounter bugs in the form of exceptions (both logical such as EConvertError and hardware such as EAccessViolation). The tricky part is that only address of where the exception occurred is reported by the default Delphi exception handler. This is more often than not, less than helpful. Typically, that address will map to a line deep inside the VCL or RTL. What we’re really interested in is how we ended up there in the first place with invalid parameters (i.e. a blank string or a nil pointer). To get that we would need a complete stack trace of the calls that ended up in the exception being raised.

This article is about developing such an exception stack tracer. Not only will it show a complete stack trace leading up to an exception, but in the presence of so-called Run-Time Location Information (RTLI), it will also give a complete symbolic stack trace. "

"I remember reading an excellent article about PE files by Matt Pietrek[i]. In it he describes how implicit linking to external DLLs work. About the import address table, he says:

"Since the import address table is in a writeable section, it's relatively easy to intercept calls that an EXE or DLL makes to another DLL.. Simply patch the appropriate import address table entry to point at the desired interception function. There's no need to modify any code in either the caller or callee images. What could be easier?"

Yeah, what could be easier <g>? Such a statement just screams: “Implement me!”. We will implement a completely general way of hooking any routine in any implicitly loaded DLL. We can then use this technique to hook the Kernel32.RaiseException routine that is called from System._RaiseExcept. "

function HookedExceptObjProc(P: PExceptionRecord): Exception;begin// Non-Delphi exceptions such as AVs, OS and hardware exceptions// end up here. This routine is normally responsible for creating// a Delphi Exception object corresponding to the OS-level exception// described in the TExceptionRecord structure.//// We leave the mapping to the standard SysUtils routine,// but hook this to know about the exception and call our// event.

// First call the original mapping function in SysUtils Result := SysUtils_ExceptObjProc(P);

// Run the event if it has been assignedif Assigned(ExceptNotify) then ExceptNotify(Result, P^.ExceptionAddress, true);end;

"The definition of what might be useful context information can vary according to what kind of application you are developing. The name of the currently focused form, the name of active database tables, the name of the logged in user and other global information might be useful. You can easily add any such value-added information yourself.

However, in all cases, a complete overview of the function calls that preceded the raised exception will be most useful. To get that, we have to implement something called a stack tracer. A stack tracer will analyze the current contents of the stack and try to figure out the return addresses stored there by the CPU as part of the CALL instruction operation.

YAST Nostalgia

[...] I have now converted [the 16-bit YAST stack tracer] to a 32-bit version and added some bells and whistles along the way – see the [code below]"

unit HVYAST32;// Yet-Another-Stack-Tracer, 32-bit version//// Loosely based on my 16-bit YAST code published in// The Delphi Magazine, issue 7.//// Description: A general call-back based stack-trace utility.// Both stack frames based and raw stack tracing is supported.//// Written by Hallvard Vassbotn, hallvard@balder.no, July 1999//interface

{$W-}// This routine should not have a EBP stack framefunction GetEBP: pointer;// Return the current contents of the EBP registerasmMOVEAX,EBPend;

function GetESP: pointer;// Return the current contents of the ESP registerasmMOVEAX,ESPend;

function GetStackTop: DWORD;asm// Pick up the top of the stack from the Thread Information Block (TIB)// pointed to by the FS segment register.//// Reference: Matt Pietrek, MSJ, Under the hood, on TIBs:// PVOID pvStackUserTop // 04h Top of user stack// http:{msdn.microsoft.com/library/periodic/period96/periodic/msj/F1/D6/S2CE.htm }//MOVEAX,FS:[4]end;

// Now check to see if the instruction preceding the return address // could be a valid CALL instruction if Result thenbegin// Check the instruction prior to the potential call site. // We consider it a valid call site if we find a CALL instruction there // Check the most common CALL variants first CodeDWORD8 := PDWORD(CodeAddr-8)^; CodeDWORD4 := PDWORD(CodeAddr-4)^;

// Get the current stack from from the EBP register StackFrame := GetEBP;

// We define the bottom of the valid stack to be the current EBP Pointer // There is a TIB field called pvStackUserBase, but this includes more of the // stack than what would define valid stack frames. BaseOfStack := DWORD(StackFrame) - 1;

// We will not be able to fill in all the fields in the StackInfo record,// so just blank it all out first FillChar(StackInfo, SizeOf(StackInfo), 0);

// Make sure the global variables are correctly set InitGlobalVars;

// Clear the previous call address PrevCaller := 0;

// Get a pointer to the current bottom of the stack StackPtr := PDWORD(BaseOfStack);

// Loop through all of the valid stack spacewhile DWORD(StackPtr) < TopOfStack dobegin

// If the current DWORD on the stack,// refers to a valid call site...if ValidCallSite(StackPtr^) and (StackPtr^ <> PrevCaller) thenbegin// then pick up the callers address StackInfo.CallerAdr := StackPtr^;

// remeber to callers address so that we don't report it repeatedly PrevCaller := StackPtr^;

// increase the stack level Inc(StackInfo.Level);

// then report it back to our caller ifnot ReportStackFrame(StackInfo, PrivateData) then Break;end;

"To Stack Frame, or not to Stack Frame – that is the Question

There are generally two different types of algorithms to choose from when implementing a stack tracer: the more elegant stack frame based algorithm and the raw brute force algorithm.

[...]

The frame-based stack tracing is elegant and fairly fast, but it has one major weakness. It will not find callers that have no stack frames. With the current crop of optimising compilers, most smaller routines will not have stack frames and this reduces the usefulness of the stack tracer dramatically. There are two solutions to this. Either force stack frames for all your code – and preferably the VCL and RTL, too. Or use another algorithm.

[...]

[T]he brute-force method is much more primitive. The algorithm is very easy: just look at all the DWORDs stored on the stack. If a DWORD happens to be a value that falls within the valid code segment of this module, include it in the stack trace. To avoid getting too many false positives, we can add some more constraints."

"Dusting off the RTLI

While having the stack trace in hand is a great step in the right direction, it is still rather cumbersome having to locate the correct copy of the project’s MAP file (providing that we have it somewhere) and then start searching for each logical address from the stack trace.

Ideally, the stack trace itself should include symbolic information such as the unit name, filename, line number and routine name the logical address corresponds to. Thanks to Vitaly Miryanov and his RTLI[ii], we get this wonderful capability almost for free. He has already developed the framework and set of routines to make this possible. We just have to tweak the code a little to make it work with the newer compiler versions."

HVEST was a step in the right direction and using it is certainly better than nothing. If you are already using it you your code today, by all means continue to do so. But time has moved on and there are now more mature solutions available - including the open source JclDebug (as part of the JCL library) and the commercial madExcept, Exceptional Magic and EurekaLog. JclDebug was in part based on my HVEST code and brought forward by Petr Vones and others. If you haven't already, you should seriously consider using one of these - you will not regret it, believe me! ;)

Tuesday, March 11, 2008

"I don’t miss many features from Microsoft’s Visual C++ 6.0 when working in Delphi, but the new /DELAYLOAD option of the linker is one of them. This option lets you turn normal, implicit DLL import libraries into so-called delayload import libraries. This means that the DLL will not be loaded by the operating system (OS) during start-up of the EXE file, but rather on an as-needed basis when you actually call the routines. The first time a specific DLL routine is called, the DLL is loaded with LoadLibrary and the routine address is retrieved with GetProcAddress. This is accomplished simply by turning on the /DELAYLOAD option of the linker, specifying what DLLs you want to be delayloaded. In this article, we will show how we can implement a framework for easily accomplishing similar behavior in our Delphi applications."

This is one of the TDM articles I'm most satisfied with. It covers a fairly useful subject and technique and it contains some tricky, hacky code that is challenging to explain and get your head around. It is a neat hack that feels a little bit like magic ;).

The goal we should set is to write a support unit that will enable us to do dynamic explicit linking just as easily as implicit linking. For the solution that we will go through, we will actually achieve all the stated benefits while being able to write simple import units like the one [below]."

To allow us to use the procedural variables without more code than we saw in Listing 5, we must somehow dynamically compile code thunks similar to the ones we saw back in Listing 3. This requires acting like a mini-compiler and generating executable code on the fly. To complicate matters, we have to preserve the stack-layout and the contents of parameter passing registers (EAX, EDX and ECX). A single set of code must handle all cases of calling conventions and parameters.

As the first step, the CreateThunks method is responsible for dynamically creating these code thunks. Essentially, it allocates a block of memory and then fills it with CPU instruction op-codes, see [the code below]."

When one of the procedural variables are called through, control will be transferred to the corresponding thunk. From here it calls back up to the per-DLL header, pushes the Self-pointer and jumps on to the ThunkingTarget procedure. This procedure is a bit tricky and it has to be written in assembly to allow us to save the contents of certain registers, see [the code below]."

We have now been through the inner workings of the HVDll unit. What might be more useful in the long run, is to know how the classes can be used for everyday work. I have included the public interface of the TDll class [below]."

Thursday, March 06, 2008

"In their book Design Patterns, Gamma et al (a.k.a. the gang of four) lay the foundation for a new way of approaching software design. [...] In this article we will first look at the language elements that are unique to Object Pascal when compared to C++ and how this makes many of the problems the design patterns try to solve, non-existent, or at least much easier to solve. Then we will look at one example of a very simple design pattern, the Singleton pattern, and how this can best be implemented in Delphi."

This is one of my higher level TDM articles. It revolves around the discussion of the Singleton pattern and implementing it in a reusable fashion in Delphi. Singleton is one of the design patterns with a more dubious value - it is not well suited for multithreaded code and often it preemptively decides that there should only be a single instance of a specific class. Nevertheless, it can have its uses and the article does show some hacks to make the default constructor and destructor unavailable, for instance.

"Even if the goal of designing a Singleton class might seem very simple, there are a number of points we must consider:

· When and by whom should the single instance be created?· When and by whom should the single instance be destroyed?· How should external clients get access to the single instance?· How can we avoid that the value of the instance reference is corrupted?· How can we avoid illegal creation of additional instances?· How can we avoid illegal destruction of the single instance?· How can we keep the design of the Singleton class, but still allow extension by inheritance?"

At the time, class variables were not present in the language, something I bemoan in the article. However, my idea of a useful class variable implementation differs from what we eventually got (and what most sane men would expect ;) ).

"Class fields is such a unusual concepts for most Pascal programmers, so many find it hard to grasp how they should work, if they were part of the language. In OP we do have hard-coded, read only class fields, such as ClassName, InstanceSize, RTTI pointers etc. These are accessed through class functions, but the actual information is stored as part of the extended VMT (virtual method table). This is how class fields should be implemented as well. A class field follows the VMT, so each new derived class has a separate copy of the class field slot."

So I wanted proper per-class (per-VMT) class variables, not the global-variables-in-disguise class vars we have now (each child class shares the class var it inherits with all other classes in the same part of the hierarchy). This has since been discussed in this log here and here.

Another amusing part of the article is my need to uphold the merits of the Delphi Object Pascal Language.

"Object Pascal as a better language

Many people (not to mention the popular computer press) tend to believe that Object Pascal (OP from now on) has only a subset of the language features of C++. While it is true that OP lacks features like multiple inheritance, operator overloading (except for the array subscript operator [..]) and templates, it still has an array of language features not found in C++. Over the years OP has borrowed many features from C++, for good or for worse. I sincerely hope they will not copy all of them – C++ is such a complex language with many pitfalls for both the novice and experienced programmer.

Well, today we do have proper operator overloading and a template-like facility is (or will become for Win32) available in the form of generics. Still, I do stand by the statement that Object Pascal is a rich, capable and easy-to-use language.

I think the original plan was to write more articles about design patterns; general discussion, sample Delphi implementations, recognizing existing use of patterns in the VCL and so on. But they never materialized - not in print, anyway; I did stumble over a draft of patterns in the VCL. Maybe I'll revive some of that material on the blog later.

Sunday, March 02, 2008

One of the key reasons that computers have conquered the world is that they have been following Moore's Law with faster, smaller and cheaper CPUs (and similar "laws" and improvements of memory, hard disks, graphics cards, etc) coming out every year.

Until recently, all programs have just become faster and faster due to improved hardware. This has been dubbed "the free lunch" and has given sloppy programmers the "hardware-will-catch-up" excuse to write slow and bloated software.

Well, no more (this DDJ piece by Herb Sutter is recommended reading). The speed of normal run-of-the-mill single-threaded code are not getting any speedups any more. The main reason for this is that CPU clock speeds have hit the ~3 Ghz speed limit. On the other hand, CPUs are getting better at doing things in parallel - by packing multiple cores in the same die, multiple threads of execution can run at the same time. To exploit this parallelism, programs have to somehow execute multiple threads - so called multithreaded programming.

Even in the classical case of a single CPU core, there can often be substantial benefits of dividing the work of a program into multiple threads. You can improve user interface responsiveness by off-loading some of the heavy lifting to a background thread, for instance, while the main thread is still happily updating the GUI.

Delphi has always (well, since Delphi 2) anyway had some level of support for writing multithreaded applications. There is the TThread class that encapsulates the concept of a separate thread of execution and there are wrappers for critical sections, mutexes, semaphores and events. Allen Bauer is doing an admirable job of thinking, designing, (re-)implementing and writing about an upcoming Delphi Parallel Library (DPL) in his blog.

Still, one of the major weaknesses of the current Delphi VCL thread support is that there is no (easy) way for the main thread to wait for a signal in a non-polling, non-blocking fashion. Another related issue is that there is no clean way for threads to communicate between themselves or the main thread. For performance and blocking reasons, the dreaded TThread.Synchronize method should be avoided.

These are the main points I raised in The Delphi Magazine article Knitting Your Own Threads, published in December 1998 (time sure is flying, that is almost 10 years ago now! :)). It also goes into some detail the various threading support in the compiler, RTL and VCL (we are still in the Delphi 4 era here). It talks about and digs into the implementation and shortcomings of:

threadvar

MainThreadID

IsMultiThread

BeginThread / EndThread

TThreadFunc

TThread (Execute, WaitFor, Synchronize)

TThreadList

TEvent

TCriticalSection

Then it goes on to try and fill in some of the shortcomings, giving implementations and wrappers for (some of these have been covered in later Delphi releases):

TSynchroObject

THandleObject

TNamedObject

TMutex

TSemaphore

TWaitableThreadList

TMultiThreadedMainLoop

MsgWaitForMultipleObjects (hooking Applicaton.OnIdle)

TSignalList

A few excerpts of the article and code:

"[The TWaitableThreadList] class can be used to administer a background working thread. The thread class will keep two TWaitableThreadLists, one InBox for work to be done and one OutBox for worked finished by the thread ready to be picked up by the main thread (or even another work thread for further processing),see example work flow in Figure 2. "

// Get the Signal associated with this index and trigger the event TCustomSignal(FList.List^[Index]).Trigger;end;

function TSignalList.WaitOne(WaitTime: DWORD; varIndex: integer): TWaitResult;// We use the blocking function MsgWaitForMultipleObjects to wait for any// message in the message queue or any signaled object from any of the// other running threads in this process. See WINAPI32.HLP for details.var WaitResult: DWORD;begin// This call will block and use 0% CPU time until:// - A message arrives in the message queue, or// - Any of the object handles in the Objs array become signaledif IgnoreMessagesthen WaitResult := WaitForMultipleObjects(FList.Count, @FObjs, WaitForAll, WaitTime)else WaitResult := MsgWaitForMultipleObjects(FList.Count, FObjs, WaitForAll, WaitTime, MsgWakeupMask);

// Index is only valid when Result = wrSignaledIndex := WaitResult - WAIT_OBJECT_0;

"Now that we have a nice encapsulation of MsgWaitForMultipleObjects to work with, lets continue with adding the improved threading capability to the main thread of the application (and thus the VCL). As we discussed, this is accomplished by hooking the OnIdle event of TApplication. See the source code of the TMultiThreadedMainLoop class in the HVMultiThreadMain unit."

procedure TMultiThreadedMainLoop.AppIdle(Sender: TObject; var Done: boolean);// Whenever the application becomes idle, i.e. there are no messages in the// message queue, this procedure is entered.begin// The default case for the old idle event// handler should be that it is done processing Done := true;

// Call any old idle event handler// - this could be extended with an idle hook chainif Assigned(FOldAppIdle) then FOldAppIdle(Sender, Done);

// WaitUntil handles all signaled objects for the main threadif Done then// If the old idle event handler is done,// wait until there is a message for us (blocking) FSignalList.WaitUntil(INFINITE, [wrMessage])else// If the old idle event handler is not done yet,// just check for signaled objects or messages (non-blocking) FSignalList.WaitUntil(0 , [wrMessage, wrTimeOut]);

// Tell the timer-loop that we have actully been idle FHasBeenIdle := true;

// Now return to the message loop in TApplication and// let it have a look at the message for us// Note that we will normally return with Done = true.// This will call WaitMessage in TApplication.Idle, but it will not// block because we already know there is a message in the message queueend;