DLL or static lib?

Discussion about everything. New games, 3d math, development tips...
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

DLL or static lib?

Post by MasterGod »

At which situations should I choose to create a DLL/Static library?

What are the dis/advantages of each of them?

Thanks in advance :)
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
Sylence
Posts: 725
Joined: Sat Mar 03, 2007 9:01 pm
Location: Germany
Contact:

Post by Sylence »

A static library is great when you don't want to release a package of 20 or more files, or if you want to keep the package small (the linker only link code that is actually used).

A dll is good when you need the same code for more than one program. Also when you have DLLs you can update the dll without touching the executable which should make the patches smaller
Software documentation is like sex. If it's good you want more. If it's bad it's better than nothing.
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Sylence wrote:A static library is great when you don't want to release a package of 20 or more files, or if you want to keep the package small (the linker only link code that is actually used).
1. Why would you need N files when you Don't use static lib? - I mean I don't understand which problem does it solves?
2. What do you mean by "the linker only link code that is actually used" - There is code that is used under some condition..
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
Sylence
Posts: 725
Joined: Sat Mar 03, 2007 9:01 pm
Location: Germany
Contact:

Post by Sylence »

You would have the executable plus all the dlls.

Let's assume you have a library with the two functions A() and B() and a program that uses just A().

When you use a static lib the linker will only link the code of function A() into the executable but B() will be ignore until it is used in your executable.
If you would use a DLL, it would also contain the code for B() which is never used so a waste of space.
Software documentation is like sex. If it's good you want more. If it's bad it's better than nothing.
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

But if B() isn't being linked then how can it be called later - "until it is used in your executable"?
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
Sylence
Posts: 725
Joined: Sat Mar 03, 2007 9:01 pm
Location: Germany
Contact:

Post by Sylence »

when you call B() from your executable the linker will link the code of B() to your executable when you recompile it
Software documentation is like sex. If it's good you want more. If it's bad it's better than nothing.
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

I mean if in my library have something like this:
if (A()) B();
Then would it then link both A() and B()?
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
ssexton
Posts: 54
Joined: Wed Oct 25, 2006 7:46 am
Location: South Florida
Contact:

Re: DLL or static lib?

Post by ssexton »

MasterGod wrote:At which situations should I choose to create a DLL/Static library?
That's easy: use a DLL and forget about static lib. The only reason to use a static lib is if you're too busy to make a .dll or don't know how. I use DLL for everything, and never use static libs.

Off the top of my head, here are some of the differences:

- build times: linking the DLL stubs into your main is faster than linking the entire function code every time from the static lib

- maintenance: with a DLL, if you change it, you don't have to remember to recompile the main program also. The changes get picked up automatically at runtime. With a static lib, if you fix a bug in the lib but forget to rebuild the main, the main still has the bug because it has old code. You'll regret using static lib the first time you do this.

- number of files: static lib goes into your .exe, so one file. DLL doesn't, its a separate file to install. Or more, if you use lots of DLL's. Big deal.

- symbol clashes: every non-static function in a static lib has the potential to cause a symbol conflict when you link. with DLL, its only the symbols you choose to export. Either way, possibility of a clash increases with the more code you have. Its just much easier to control with a DLL.

- code size: they are the same. with a static lib, the linker pulls in only the .obj's you reference (usually its the entire .obj not the individual function). with a .dll, the linker only pulls in the .obj's that are referenced from the symbols you export. With Irrlicht specifically, this is mostly irrelevant since its very hard _not_ to reference every single method in the entire library, due to how the API is structured (your .exe references the IrrlichtDevice, and the device references pretty much everything else, usually via a virtual so the linker has no way to optimize away the methods you're not using).

- load time: a toss up. It used to be that having a bunch of .dll's meant longer load times because all the .dll's have to be searched for, loaded and relocated when you start up the program. Less true these days with preferred addresses, dll caching, delayed loading, fewer public symbols, etc. Dll can even be faster with delayed loading (ymmv), since the OS only loads the smaller main .exe before it calls your main().

- plugins: if you need a plugin architecture, you can only do it with a DLL

- LGPL license: DLL much preferred if you're talking about LGPL'd code. With static lib, you have to distribute all the .obj's from the main program. With DLL, just the .dll and its .lib files.

- DLL Hell: static libs are immune to this. On Windows, it is easy to avoid this for the most part just always put the .dll in the same directory as your .exe. On Mac, ditto if you use private libraries/frameworks (install name starts with @executable_path). No good solution on Linux, unless you think you can get away with using /usr/lib or /usr/local/lib (and sysadmins will hate you for that). In case you're not familiar, "DLL Hell" is the problem of 1) loading the wrong copy of the DLL, if >1 copy is installed on the system, and 2) not able to load the DLL, because it can't be found or because the exported symbols changed. The DLL search path is the cause of most of these (not the symbol issue) which is why you install those specific locations. Forgetting to install the DLL can also be a problem, esp. when you use a DLL that uses other DLLs that uses other DLLs...

- embedded systems: with something like busybox, you can get your code size way down by static linking. This is really the only situation where a static lib might make sense, when you're targetting a very constrained device and every byte matters. Otherwise, I don't think the headaches are worth it.

- sharing code between .exe's: doable with a DLL. Not possible with a static lib, because each .exe gets its own copy.
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Wow, thanks, that is indeed a lot of information I needed.

PS: I don't want to open a new thread about this little question so..: Is it possible to make a dll in vc EXPRESS?

Edit:
No.
Last edited by MasterGod on Fri Feb 01, 2008 3:41 pm, edited 2 times in total.
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Re: DLL or static lib?

Post by rogerborg »

MasterGod wrote:At which situations should I choose to create a DLL/Static library?
That's easy: for the purposes of developing a game, use static libs and forget about DLLs. The only reason to use a DLL is if you're too lazy or impatient to use a static lib or don't know how. I use static libs for everything, and never use DLLs.

Off the top of my head, here are some of the differences:

- build times: linking a full lib into your main is insignificantly slower than linking a DLL stub.

- maintenance: with a DLL, if you change it, it's not obvious that the main program is going to behave differently, which can screw you or your users unexpectedly. You'll regret using a DLL the first time you do this. With a static lib, it's clear to anyone with half a brain when the whole exe has or hasn't been rebuilt.

- number of files: static lib goes into your .exe, so one file. DLL doesn't, its a separate file to install. Or more, if you use lots of DLL's.

- symbol clashes: every non-static function in a static lib has the potential to cause a symbol conflict when you link. This is great, as it forces you to code in a modular fashion, and it's obvious during link. This also helps you to avoid getting screwed by characteristically sloppy third party DLLs that suddenly declare a public symbol that clashes with one of yours.

- code size: they are the same. In most cases during games development, the linker shouldn't be discarding unused symbols anyway.

- load time: insignificant for games. Runtime initialisation dwarfs any code loading time.

- plugins: if you need a plugin architecture, you can only do it with a DLL. However, that only applies to third parties, not to your internal development.

- LGPL license: don't use G/LGPL code, ever.

- DLL Hell: static libs are immune to this, which is why you should use them.

- embedded systems: with something like busybox, you can get your code size way down by static linking. This is one of the many reasons why a static lib might make sense.

- sharing code between .exe's: is irrelevant for the purposes of games development.

- security risk: it's trivially easy for hostile users to write a shim dll that wraps your real DLL and fiddles with the calls. Using static libs won't stop a determined hacker, but there's no point in keeping the bar so low.

You may choose to take this advice seriously, or merely as a suggestion that you should do some more research before making a decision that's appropriate for your project.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Thank you both for showing me both sides of the coin.
I guess I'll have to think deeply about my project and then decide which way is better of it.

Thanks again, it helped me a lot.
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
ssexton
Posts: 54
Joined: Wed Oct 25, 2006 7:46 am
Location: South Florida
Contact:

Post by ssexton »

@rogerborg: Nicely done. I figured someone would react the way you did. It would have been more impressive if you'd put some effort into it rather than just reversing everything I said. For now, I'll pretend that it wasn't just a knee-jerk reaction to my blanket statement "forget about static lib", and that you're actually trying to bring up valid counterpoints. That said:

Your restatement of build times: just not true. Unless, I suppose, your static lib is trivially small. There is much more .obj code in a static lib that needs to be processed (its all of the "real" code) compared to a dynamic lib (its just the stubs).

Maintenance: Agree with your statement about DLL changing main behavior unexpectedly. That's a dual-edge sword - both an advantage and a disadvantage. For example, if I happened to ship an Irrlicht.dll that had a memleak, it wouldn't bother me _in the least_ for an end user to replace it with an updated version that doesn't have the leak. Yes this can be a security risk (shim dll's, as you pointed out, see below). Totally disagree with your statement about "half a brain knows when the whole exe has or hasn't been rebuilt". That's actually THE #1 REASON I recommend against using static lib: it just doesn't work that way in practice (ymmv, I suppose). Its very easy to end up with stale code, esp. during development time. Having to link twice instead of once when you change the library code is a PITA. Might as well just put the .cpp's directly into your main .exe (see below).

Symbol Clashes: Clearly you've never had issues with integrating 3rd party static libs. The statement you made about 3rd party DLLs declaring clashing symbols applies with statics too, but it is much much worse, since you clash with every symbol (intended as public API or not) in the 3rd party code.

Load Time: Agree, in the context of games, the amount of time you spend loading other stuff (media files) is orders of magnitude larger than the code loading time. I only put this in because for awhile, on *nix platforms, the load time for dynamic libraries was ridiculous, and if I didn't bring it up, someone who knew that history might. It is a consideration. Or used to be.

Plugins: First parties can have perfectly valid reasons for using a plugin architecture. Been there, done that. Its a natural choice when you find that GoF's Bridge pattern applies. To use Irrlicht as an example: why load the DX9 code into your process if the user has selected OGL? or vice versa. Assuming you give the user a choice in the first place, that is - if you hard-code one or the other, yes you can just compile it out. Similar reasoning for the media loaders - again, assuming you give the user a choice (think modders) and don't just hard code what you're currently using. I'm not saying this should be done - certainly if enough of the Irrlicht user base hate DLL's as much as you do, it won't - just an example of why you might want a plugin architecture, if you do something similar in your game.

LGPL: Agree - avoid GPL, unless you also intend to make _your_ project GPL. Its a viral license, you can't use GPL code unless your code is also GPL. Period. It means you can't distribute your binary without giving the code away (if you don't intend on distributing the binary, for ex: a hosted game server, GPL is still an option at least until they close the "service provider hole"). LGPL is less evil: if you use a DLL version of LGPL code, yes it is inconvenient to have to include a bona fide offer in your doc telling users that they can get the source code from you. But don't let that scare you off. If the best tool for the job is LGPL, the license alone doesn't make it unusable.

DLL Hell: *shrug* People make too much of this. It is trivially manageable as I mentioned.

Sharing Code: maybe irrelevant for certain classes of games. Not irrelevant for all.

Security Risk: Good point, but one I think is completely irrelevant. Someone who wants to hack your game, will. And except in the case of network games (or other cases where the "cheat" of one player affects other players), who cares? Besides, anyone who wants to reverse engineer your API's isn't going to be flustered by the need to call OpenProcess or use a binary patcher to defeat the "safety" you thought you had because you used static libs. The hard work is reverse engineering the code. Take a look at all the Diablo II, ahem, "mods", that are out there - not having DLL's didn't help them. Hell, even using Win32 Security calls to try to block OpenProcess didn't help them.

Patching: I didn't think of this until just now. By virtue of being a separate file, it is easier to distribute incremental patches if you use a .dll. It is a possible strategy if you want to have your game apply patches (think MMO). Delay loading your .dll's until _after_ the patcher runs, then code patching becomes a trivial matter of replacing the files. Much harder if all you have is a big .exe, since then in order to automate this you have to mess around with having one .exe (the patcher) launch another (the game). Granted that's the way a lot of companies do it, and it isn't hard (but still more involved than the .dll way), but that doesn't make it a good idea.

---

@MasterGod: Another way to think about this (and the real reason I wanted to follow up, besides just having time to kill waiting for a 40 min regression test to run...) is to think about what a static lib and a DLL actually *are*. Most of the adv/dis mentioned above (and others you can probably think of on your own) naturally fall out of this.

What is a static lib? A static lib is essentially a .zip file containing all your .obj's. Its not actually in .zip format, it'll be in a linker-specific archive format. But otherwise, that's ALL it is. The only difference between using a static lib and including the .cpp's directly in your main project, is that when you compile the main, you save the time of having to compile the C code. You still have to link it all. Its a mixed blessing. Build time is faster because you skip the cc step. But because you skip the cc step and because you still have to link, you can get stale code if you update the lib but forget to update the main. etc. etc. This is why I say forget about static libs. If you think that is what you want, you may as well just put the .cpp's all in your main program. Sure it'll take longer to build (because you run cc every time) but you'll get all the other benefits of using a static lib without its disadvantages. If you're coming up with reasons to split up the code, you might as well do it right and make it a standalone entity (DLL) and deal with the issues. For me, the savings of not running cc (but still needing to running ld), compared to the problems it can cause (double linking, stale code) takes static lib completely out of the picture. DLL or monolithic code are the worthwhile options, IMO.

What is a DLL? In a very simplistic sense, it is an .exe that doesn't have a main(). It is real, compiled code. Its a bit like having a second "helper" .exe, except that it runs inprocess and you use function calls to interact with it (contrast with, say, pipes or sockets or whatever you might use if it were a real, separate .exe, a CORBA or COM server, etc). When you link to it, you are combining your .exe with "stub" information that tells the OS how to find the .dll code at runtime (name of the .dll file, ordinal numbers of referenced methods). You can tell the OS to delay loading it until it is used (and if it never is, it doesn't load). You can even control the loading of it yourself (plugins). When you export symbols from the .dll, you are precisely specifying the way that other code interacts with it. And as long as that interface doesn't change, that is why you are able to modify the DLL without modifying the main, why you have less risk of symbol clashes (because it is a separate entity from your main, with much smaller interface points), why you can get DLL Hell (because the wrong file gets found at runtime), etc etc.

In the end, of course, make up your own mind. I made the blanket statement "forget about static lib", because you asked for advice, and that is the advice I would give you if you had asked me in person. The rest of this is in case you (or anyone else) really wants to go through the exercise (not sure if you expected to get this much info!), rather than take the 2-minute executive summary at face value and just accept it.

Apologies for the size of these responses. SWEng topics like these always make me run long.
ssexton
Posts: 54
Joined: Wed Oct 25, 2006 7:46 am
Location: South Florida
Contact:

Post by ssexton »

MasterGod wrote:PS: I don't want to open a new thread about this little question so..: Is it possible to make a dll in vc EXPRESS?
I *think* so. I remember reading a story about someone building an IDE extension with Express (which I think was a DLL) and getting in trouble for it. But, I had the bucks for the full version VS 2005 so I really don't know. For me, its just a matter of picking the right project type when you do "New Project" (under Win32 Application, iirc - I always select Empty Project and set it up manually from there, but you might find the other options useful). If you have that option in Express, that's the way to do it.

Assuming M$ didn't purposely cripple express so that you really can't do it (I wouldn't put it past them), even if there is no template you should be able to manually get the linker to do it. iirc, from the command line its LINK.EXE /DLL, and there should be a setting in the IDE that matches, but honestly, it has been a very long time since I did it the hard way. You might need to spend some quality time with MSDN to figure it out. Which is a good idea anyway, there is literally a TON of info on MSDN, for free.
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

ssexton wrote:Apologies for the size of these responses. SWEng topics like these always make me run long.
Apologies? - You certainly do not have to. Thank you (and rogerborg) for being that specific, the more specific you are the more I understand and learn.
Last edited by MasterGod on Fri Nov 02, 2007 11:47 pm, edited 1 time in total.
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

I think I just got a headache from reading that.

good stuff guys I had no idea the differences run that deep.

you boys know your stuff thats for sure.
Post Reply