“Reaching for the gods” is the second book in “Delphi in all its glory” series. It was released January 2024.
Order the book in electronic of printed format.
Book details
Book Layout
This book is hands-on, pragmatic, and focused on solving real-world issues.
We’ll start with an in-depth look at the Delphi compiler (linker, precompiled libraries, library paths). Then, we’ll move on to advanced debugging: reading call stacks, using advanced breakpoints, remote debugging, and leveraging third-party tools for automated bug reporting and crash data collection. You’ll learn to how to set the compiler to help you pinpoint crashes and even prevent them entirely on your customer’s computer.
Next, we’ll tackle memory management (memory ownership, preventing and dealing with memory corruption) and proper exception handling (covering crashes, access violations, nil pointers, etc). For legacy developers, there’s a section on modernizing old Delphi code for safety, speed, and 64-bit compatibility.
Additional topics include version control, multi-threading, Windows messages, and avoiding common pitfalls like buffer overflows, Application.ProcessMessages, abusing pointers, etc.
I promise that by applying the concepts in this book, your application will run smoothly—without any crashes!
The Trilogy
This is the second book in a trilogy focusing on code safety and proper architecture design.
This trilogy emphasizes building stable programs through reliable code, avoiding common programming pitfalls, transforming mundane Delphi features into an error-prevention system, and understanding why some programming concepts are inherently safer than others.
Writing Style
The tone is fast-paced, light, and often humorous. There’s no “just trust me” here—every claim is backed by evidence: links to white papers, scientific articles, proven concepts, code examples, and benchmark tests.
TOC
1. Intro
2. Table of content 8
3. The Delphi compiler 22
What is a compiler? What is an interpreter? 23
Compiled vs interpreted 23
A reliable compiler 25
The toolchain 27
Executable size 28
Compiler speed 29
From Pas to Exe 31
The compilation order 33
Compiling and running the program 34
DCUs 35
Debug vs Release DCUs 35
The linker 39
Compile vs Build 40
Improving compiler’s speed 41
Remove unused units 41
Rearrange the units in the uses section 42
Unused paths 43
4. Libraries 44
Why do we need libraries? 45
Libraries are not for everyone 45
The four rules of creating packages 47
Library architecture 49
Circular references 51
It is all about aliens and pyramids 52
The anatomy of a package 53
DPK 53
BPL/DCP 58
Project groups 62
Compiler Directives 63
Delphi’s framework 64
The RTL library 64
The VCL library 65
Library paths 66
Environment variables 66
Compiling with multiple Delphi versions 69
Finding files via Library paths 70
Search Paths 79
Under-development libraries 79
Global vs local paths 80
Precompiled files 81
Precompiling our own files 82
The “Package/DCP/HPP output directory” fields 83
Project Paths 84
Recap 84
How to install a library? 86
Installing a library manually 86
Single-file libraries 91
What to do when things go south? 91
Library folder structure 92
Installing libraries via Setup 93
Creating our own installer 93
IDE plugins 94
Installing libraries via GetIt 95
How to uninstall a library 96
Runtime/Designtime libraries 97
Run-time libraries 97
Design time libraries 98
Design time vs Runtime 98
Including a library in our project 99
Linking with runtime packages 101
Drawbacks 102
How does the linker optimize unused code? 104
Experiment calibration 106
Proceedings 106
Extension to the experiment 112
Debugging 3rd party libraries 114
Recompiling parts of the VCL 117
Why libraries are mandatory for large projects? 120
Logic separation 120
The Chaos of Monolithic Projects 125
The Breaking Point 125
The Refractory Ignition Spark 125
A Better Way: Modular Code via Libraries 126
Overcoming Preconceptions 126
Using C/++ libraries in Delphi 128
When you have the source code 128
When you have the DLL 128
Popular libraries 131
LightSaber 134
Proteus 143
About libraries and licenses 157
Meaning of the fields 157
Discussions 159
Conclusions 160
More details 160
The Initialization of packages 161
The Register procedure 163
Building our own visual components 165
5. Automatic compilation 169
Using MSBuild in Delphi: 170
6. The debugger 174
What is a debugger? 175
Preparing our project for debugging 176
Stacks 176
Configurations 178
The “Compiling” page 179
The “Use debug DCUs” field 182
Other settings 184
A picture is worth a thousand words. 184
The “Linking” page 186
The “Debug source path” field 188
Breakpoints 190
Breakpoint properties 191
Relocate the execution point manually 192
Finally, ready to debug 194
Starting the program under the debugger 194
Debugging from a crash point 196
Cannot debug? 199
Fun stuff to do during debugging 200
Hint for geeks 203
Debugging cheat sheet 204
7. Remote debugging 207
How does it work? 207
Install PAserver (on the remote machine) 208
Run PAServer (on the remote machine) 209
Configure the environment (locally) 209
Assign a Connection Profile to the Delphi project 213
Choose which files to deploy 215
Deploying the files manually 215
Start debugging 216
Stability 218
8. Automatic bug logging & reporting 220
MadShi MadExcept 222
EurekaLog 225
9. Advanced debugging techniques 228
Method 1: Attach to process 228
Method 2: Debug with “Run -> Load process”. 229
Method 3: Host application (Recommended) 234
Method 4: External tools 236
Method 5: Start Delphi in “safe” mode 236
Method 6: Use external tools 236
Stupid Windows 10 237
10. Speed up your program 238
Profiling your program 240
Home-brewed method (as cheap as the home-made beer) 240
Third party profilers (aka non-free) 242
Improving the speed 244
Record field alignment 244
CPU Optimization 248
Compared to Julia 249
11. Compiler! Please save my ass! 256
Overflow checking 258
IO checking 259
Range Checking 260
Enabling Runtime Error Checking 260
Temporary disabling range checking 262
Assertions 264
Assert vs Raise 266
Nothing comes for free 267
12. Memory management 269
FastMM 270
1. Dramatic speed increase for memory-bound operations 270
2. Prevents memory fragmentation 270
3. Better memory sharing 271
4. Safer code 271
5. No more access violations 275
Switching FastMM to Full Debug Mode 277
How to read a FastMM leak report? 278
The summary 279
Leaked blocks 279
Advanced topics 283
You create it, you kill it 283
Memory ownership 284
Dangling references 284
Alice loses her preferred book 284
Getting our dirty paws on a dangling reference 285
The root of all evil 288
There are even worst scenarios 289
Do some noise 289
Bruce Willis (and FastMM) saves the day… again! 291
Garbage collectors 293
About ownership 294
Passing the ownership around 295
Summary 297
13. Exceptions 298
Exception Handling 302
Let’s do the “What this code does” game 305
Amateur mistake 306
Keep it real 310
Spit, don’t swallow 311
Good boy, Debugger! 314
Ignoring exceptions during debugging 316
Try/Finally vs Try/Except 318
Raising exceptions 320
14. Windows Messages in Delphi 323
The Windows Messaging System 324
Message Handlers in Delphi 325
Practical Examples 326
15. Programmer’s toolbox 328
Delphi registry secrets 329
Restoring the registry 331
How to start a “mint” Delphi instance? 333
Total Commander 335
SoftPerfect RAMDisk 338
Version control 339
Do we need a repository? 340
Creating a new Tortoise repository 343
Revisions 345
Resolving Conflicts 347
Commit Progress 348
Icon overlays 348
Shelving 349
Normalizers 350
16. Code safety 353
Things that are ok, but dangerous 354
Don’t use pointers 354
Don’t do direct typecasts 355
Avoid threads 355
Avoid TTimer 355
Avoid using unsafe functions 355
Things related to the Delphi language 357
Use strong typing 357
Avoid “with” 357
Use assertions. Abundantly 358
Document your code 358
Follow coding standards 358
Extra care with Interfaces 358
Perform boundary checks 359
Avoid using unsafe functions 359
Handling Boundary Values 359
Dealing with Wrapping 360
Simply “don’t do it” 361
Don’t swallow exceptions 361
Don’t use Application.ProcessMessages 361
Letting the compiler to help us 362
Activate rage checking 362
Activate I/O checking 362
Activate integer overflow 362
Activate compiler hints and warnings 362
Other runtime checks 363
Enable FastMM to check for memory leaks 363
Implement “safety net” for enumerations 363
Use Free instead of FreeAndNil 363
Extra techniques 364
Test program thoroughly 364
Implement Unit Testing for your code. 364
Use a bug tracking tool, like MadShi! 364
External libraries 364
Encapsulate your code 365
Cheat sheet 366
Quantify the source of errors 368
Classification of error types: 368
Program architecture 371
Extra stuff to check for 372
On FreeAndNil 374
A word of warning on Application.ProcessMessages 376
TControl.Perform 378
Safely storing a list of objects 380
Security update 2024 385
17. Advance topics 387
Running a single instance of our program 388
How does it work? 388
Let’s see the code 389
Anonymous methods 391
Capture of Variables 392
Usage 392
Flexible Usage 393
Inline Definitions 393
Analyzing the code above 394
Multithreading in Delphi 395
Delphi’s Multithreading Infrastructure 397
Creating Threads with TThread 397
Thread Safety 398
Synchronization with the Main GUI Thread 398
Using TThread.Synchronize 398
Using TThread.Queue 399
Other synchronization mechanisms: 400
Best Practices for Multithreading 401
1. Plan Your Multithreading Strategy 401
2. Handle Exceptions Gracefully 401
3. Minimize Shared Data 401
Common Pitfalls to Avoid 401
Delphi Parallel Programming Library (PPL) 402
Hardware limitations 402
18. Migrating 32-bit Code to 64-bit: Best Practices and Considerations 404
Alternative paths 405
How to set the LARGE_ADDRESS_AWARE? 406
Before you start 407
Upgrading Third-Party Libraries 407
Adding 64-bit Support to the Project 407
Fixing the paths 407
Inspecting the code 409
Choosing the correct data types 409
Typecast from pointer to integer 411
Typecast between Record and TObject 412
WinAPI issues 413
SendMessage 413
Vcl.Controls.TControl.Perform 413
SetWindowLong/ GetWindowLong 414
SetWindowLong: 414
SetWindowLongPtr: 415
Special types 417
Avoid using LongInt 417
Extended type 417
Inline ASM code 418
Functions that return Cardinal 419
Summary 420
19. Deploying our application on other platforms 421
Android 421
Apple 422
Linux 422
Summary 424
20. Being a programmer 425
Change is good… but hard 426
On Technical Debt 433
Rocking the boat 435
So, do you still want to do it? 437
21. All good things must come to an end 440
Where do you go from here? 441
Delphi sample projects 441
Your next big project could be a game 442
About Stack Overflow 443
Fighting bullies on Stack Overflow 443
Ask the artificial intelligence 445
Video tutorials 448
Books 449
My books 450
Already published books: 450
What I have learned in the last 25 years of software development 451
22. Notes and credits 456
Contact me! 456
Disclaimer 456
Source code 456
Be environment-responsible 456
Credits 457