DLLs werden immer zur Laufzeit geladen. Allerdings gibt es zwei
unterschiedliche Mechanismen:
Was Du "statisch gelinkt" nennst, bedeutet, daß der Programmlader des
Betriebssystems beim Starten des Programmes alle Abhängigkeiten des
Programmes auflöst und erst bei vollständiger Befriedigung das Programm
auch wirklich starten lässt.
Diese Abhängigkeiten lassen sich mit depends oder dumpbin anzeigen.
dumpbin blafusel.exe /imports
Werden die Abhängigkeiten nicht erfüllt, so gibt der Programmlader eine
entsprechende Fehlermeldung aus:
"Die Anwendung konnte nicht gestartet werden,
weil xyz.dll nicht gefunden wurde"
Bei der Programmerstellung werden die so verwendeten DLLs mittels
sogenannter Importlibraries mit dem Programm verknüpft. Aus
Programmierersicht entspricht das Verhalten so verwendeter DLLs dem
tatsächlich statisch gelinkter Funktionen.
Wobei zum Compilieren und Linken nur die Importlibrary, nicht aber die
DLL vorhanden sein muss.
Zum Laufenlassen des Programmes, was auch das Debuggen mit einschließt,
muss die DLL aber zwingend vorhanden sein.
Das "dynamische Linken", wie Du es nennst, bedeutet, daß das Programm
zur Laufzeit mit den Win32-API-Funktionen LoadModule und
GetProcAddress arbeitet. Zunächst wird die DLL mit LoadModule
geladen, dann werden Funktionspointer auf darin enthaltene Funktionen
mit GetProcAddress bestimmt.
Das ist zwar von der Programmierung her erheblich aufwendiger als das
einfache #include einer Headerdatei und Linken einer Importlibrary,
bietet aber erheblich feinere Möglichkeiten der Fehlerbehandlung.
Ein so aufgebautes Programm funktioniert prinzipiell auch, wenn die DLL
nicht vorhanden ist. Es kann ein intelligentes Versionsmanagement
implementiert werden; ist die Funktion A vorhanden, aber nicht B, wird
halt nur A verwendet.