Windows DLLs: Threat or Menace?

Gordon Letwin's 1988 book, Inside OS/2, introduced me to the concept of dynamic code linking. Though the book was about OS/2 version 1.0, its explanation of DLLs applies to Windows as well, which is where the overwhelming majority of my experience originates.


June 01, 1998
URL:http://www.drdobbs.com/windows-dlls-threat-or-menace/184410810

Op-Ed: June 24, 1998: Windows DLLs: Threat or Menace?

Tim programs LegalTrax, a document management application, for

Software Intelligence, Inc. His web page is at

http://ourworld.compuserve.com/homepages/timp/, and he can be reached

at [email protected].


Letwin lists the following advantages:

  1. Smaller EXE files

  2. Change or upgrade the dynamically linked code at any time

  3. Automatic code sharing (RAM efficiency)

  4. "A final advantage of dynamic linking is that it's totally

    invisible to the user, and it can even be invisible to the

    programmer."

I must admit, it sounded great at the time, and based on the

explosion of DLLs, VBXs, OCXs, ActiveXs, and so forth in the last

decade, my reaction was not unique. But it's time to face the facts:

The idea of DLLs is a failure with almost no redeeming benefits in

today's systems.

Smaller EXE files

There are two flaws with the promise of smaller executables.

First, it hasn't happened. Are recent Microsoft Word for Windows

executables smaller than Word for DOS ones ever were? Did the Word

for Windows executables get smaller as it became more integrated with

other Office applications? I'll wait if you want to go check, but the

answer is a big "no." I admit I'm comparing apples to

oranges--current versions do a lot more than the older versions. But

an increasing proportion of that size is not code at all. How many

megabytes do you figure that animated paperclip takes up? Any savings

from sharing DLL code have been dwarfed by the growth of overall code

size.

The second failure of the smaller executable size goal is that it

doesn't matter nearly as much as it did ten years ago. Back then, 10

MB of storage could easily cost you $1,000, while today, a 100 MB Zip

disk costs $10.

Many of you may be thinking, "I'm always running out of disk space.

If all my DLLs were embedded in the executable, it would be even more

of a hassle!" While it's true that people often seem to be low on disk

space, integrating DLLs into a large executable would not aggravate

the situation. Consider how many of those DLLs are general purpose.

Maybe it's a third-party library, and the application only uses a

portion of its code. In those cases, static linkage would remove

unused portions of that library from the executable.

Also consider the problem of duplicate and orphaned DLLs, which has

created a whole new software category of cleanup programs devoted to

addressing this problem. Many applications install DLLs into the

application's directory rather than in a central location, creating

the possibility of duplicate DLLs for multiple applications. And when

an application installs its DLLs in the Windows or System directory,

there's a good chance the DLL will still be there long after the

application is gone. Cleanup software adds its own problems. The

software may overlook a duplicate or orphaned DLL, or it may remove a

DLL that is used by an existing application.

Are you sure that DLLs are saving you more space than bloated,

duplicate, or orphaned DLLs are wasting? Even if they are, the money

spent on a cleanup program probably costs the equivalent of a

gigabyte of storage space.

Change or upgrade dynamically linked code at any time

That's right, just plug in a new version of the DLL and presto,

your application has new features. Try to think of how many times

that's come in handy. It's OK, I'll wait. Stumped? Maybe I can help

jar your memory. Perhaps you've bought one of the spell-checking

upgrade packages for your word processing program. Never heard of

one? Maybe you don't shop around much. Or maybe you're like me, and

the best such an upgrade has ever really delivered is not to break

every application that was built for an older DLL.

Occasionally, developers do release bug fixes and even enhancements

in DLLs. How could this be possible if all the code was in a single

executable? Simple -- you would need to replace the whole executable.

While replacing an executable rather than a DLL would mean

redistributing a larger file, the simplicity of replacing a single

executable cannot be beat. And if the size is a significant problem,

there are patch tools that allow you to distribute the delta of the

changes to the binary.

Automatic Code Sharing

In Inside OS/2, Letwin explains that "automatic code

sharing" refers to sharing code in RAM, although it also has

connotations as a valuable design-time development practice. However,

as is the case with hard disks, the cost of RAM has dropped

dramatically since this design decision was made. A few years after

Letwin's book was written, I made the difficult (and expensive)

decision to invest in a full 640 KB of RAM. Today I have 36 MB in

assorted SIMMs that have been sitting on my desk for weeks.

Despite the extreme economic changes, it is always best for an

application to use as little RAM as necessary. However, DLLs only

save RAM when you have two or more applications that use the same DLL

running simultaneously. There are developer utilities that can help

you identify such cases. Take a look at the applications you're

running right now and try to identify the overlaps. I suspect you'll

see this come into play about as infrequently as I do, but I concede

that whatever presence it has is a benefit. In the cases where only

one running application is using a DLL, however, the DLL is probably

bloated with unused general-purpose code, and probably uses more RAM

than necessary.

"Totally Invisible"

Users cannot easily identify which application components make use

of which DLLs, and which parts are in the main executable. And

programmers can generally use the code in DLLs almost exactly as if it

were linked right into the main application.

However, I think "invisibility" should go a lot farther than that.

Do you think users understand what DLLs are and how they cause

problems? I think so. How do they know? How could they not? Have

you ever seen an application complain about a DLL not found? How

about a GPF after another application changes the DLL? The system my

kids use has batch files to swap around QuickTime DLLs depending on

the program that needs to be run. Before I hacked together this

workaround, they weren't invisible to my four-year-old son, who

couldn't even read at the time.

How about application downloads that are available in different

configurations, depending on the DLLs you already have. ICQ offers a

smaller download for "advanced users" who are sure they already have

the correct MSVC runtime DLLs. Visual Basic can also require

literally megabytes of DLLs for the simplest of applications, and

applications developed with it are frequently distributed without

these critical components.

Users shouldn't need to be aware of these nasty details, any more

than they should know if your code uses recursion or linked lists.

Like the promise of smaller executables, the promise of "invisibility"

simply hasn't come true.

The Dark Side

The biggest effects of rampant DLL usage in 1998 are:

What benefit do we get in exchange for all of this suffering? End

users really don't get any direct benefit. However, newer flavors of

DLLs (VBXs, OCXs, and so on) do include some very nice design-time

features for developers. Most support a variety of languages and

compiler brands, allowing the programmer to choose the tools best

suited for a particular application (or the particular programmer).

Additionally, advanced DLLs integrate very smoothly into modern

development environments, so DLL components can be visually arranged

into a user interface. Code integration is similarly slick, allowing

simple implementation of DLL code options and events. These advances

in programming tools do result in better programs for end users--every

programmer doesn't have to write his own serial communication library

or grid control or whatever. This is what "code sharing" immediately

brings to my mind, and development systems have made good progress in

this area during the last ten years.

But DLLs are not the only path to these features. Back in the

pre-DLL days, there were commercial code libraries, too. The

publishers usually had to support each language and compiler,

requiring significant extra work. But the bottom line was that every

programmer didn't have to write his own communication library or user

interface back then, either. The extra burden was limited to the

library publishers. Development environments were crude or

nonexistent, so the lack of polished integration was not surprising.

Just as Microsoft specified the interface between VBXs and development

environments, such a specification could certainly have been made for

statically linked libraries. Visual C++ is loaded with Wizards to

drop MFC code into your application, and you can choose to leave most

of the MFC library in a DLL or link it statically.

I think the hugely popular Visual Basic compilers (let's not

quibble; they turn source code into EXE files) make a powerful case

against the promise of DLLs. You're supposed to get magic upgrades,

right? Then why can't you make a VB3 app run better by using the VB4

DLLs? Microsoft made that option impossible, and it was probably a

wise choice. Every version of VB has used different names for its

assortment of runtime DLLs. This was not a trivial decision; most of

the runtime DLLs had only eight characters for file names, and used

two of those for "MS."

Using run-time DLLs with different names prevents version

compatibility problems. Couldn't Microsoft have made the different

versions backward compatible instead? While the newer versions of VB

have all added appreciable features, there don't appear to be major

differences in the core features. The source code has stayed very

compatible; VB5 can handle just about all of the valid code from

previous versions. How hard could it be to keep backward

compatibility with the VB functions like Mid(),

MsgBox(), and so on? Apparently, Microsoft decided it was a

combination of too much effort and too much risk.

A Simple Solution

The answer to the almost limitless problems of DLLs is obvious:

Don't use them. Wherever possible, use static linking. Imagine the

benefits. Some other developer's boneheaded installation or poorly

designed updated DLL will not break your application. Your

application won't fail because a component is missing, or because a

registry setting has been lost or modified incorrectly. Your

application won't behave differently depending on the applications

already loaded, as a DLL-based application can if another application

has already loaded a different copy of one of its components. Your

installation will be exceptionally simple, and an uninstall will be

just as easy.

I should warn you of one small hassle if you try DLL-free

development. Your users won't believe that there is only one file to

install.

Bibliography

Letwin, Gordon. Inside OS/2. Microsoft Press, 1988. ISBN

1-55615-117-9. (See Chapter 7, "Dynamic Linking.")


These op/eds do not necessarily reflect the opinions of the author's

employer or of Dr. Dobb's Journal. If you have comments, questions,

or would like to contribute your own opinions, please contact us at

[email protected].

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.