I am trying to debug a dense piece of code with multiple function calls in single lines. I want to single step through all the code that I have written, but in doing that I keep finding myself in the supplied source code, including the assembler code.
This is happening at a client's site on his machine running XE5. It doesn't happen on my own code, running XE2 and XE4.
What is the magic setting that makes this work they way I want?
The best you can do is make sure that Debug DCUs is disabled in the project options. But even doing that sometimes is not sufficient to stop yourself landing in RTL code, in modern Delphi versions. I suspect that you have Debug DCUs disabled and are being caught out by this behaviour change.
The only thing you can do is get used to knowing when to use step out (F8) rather than step in (F7), and being able to escape from a function as quickly as possible. Usually that involves putting the cursor on the last line, running to cursor (F4), and stepping in again.
You might also be interested in the Selective Debugging tool by Uwe Raabe which allows you a fine grained selection for which DCUs are used with or without debug information.
http://en.wikipedia.org/wiki/REPL Read–eval–print_loop
Is there such a thing for Delphi ?
It would be rather useful to explore DLLs such as Windows APi and sketch their usage, when dealing with border cases scarcely documented.
I tried pascal scripts, such as one in Cnwizards, but it is much less comfortable.
For example it cannot use units like Windows.pas and you had to make some strange stubs of your own for it.
And anyway, those scripts are less easy to use for "try this try that" scenario than Repl.
For Delphi objects most clsoe thing it to pause on breakpoint and use Evaluate/Modify window, but it only works with Delphi objects, not DLLs; it cannot make temporary vars to cache values and such.
It's not really what you're looking for, because Delphi is a statically typed, compiled language, but if you really insist on being able to type some pascal in and see if it does anything, you can try the TJvInterpreter component that comes in the Jedi VCL.
Note that the experience is nothing like using python. You can't just type "uses module" and hit enter, because pascal units must be complete before they can even be interpreted by JvInterpreter, and the JvInterpreter needs you to write a wrapper for every single other unit you want to import. You would go crazy. I'm not seriously advising anybody to try to build a REPL around TJvInterpreter.
The "interactive magic" element of Delphi is called the "designtime environment" and the way we build using "components". We don't even do that bit by writing code much, we do it all visually with our mouse and keyboard. It's called RAD (rapid application development) and is powered by the VCL (visual component library) in Delphi, and (like REPL) is one of the many ways of doing very-rapid development.
The other thing we have that is a lot like a REPL is this button in Delphi:
You click it, after creating a new empty project, and whatever code you added to your new empty project is built and running in less than a second. Close enough to a REPL for me. It's kind of like binary executable instant bliss.
Write one line. Build and run (1 second). Instant.
Sometimes when debugging, specifically when catching an exception and following through destructors called, Delphi steps through a lot of assembly code. Hit Shift+F8 appears to cause mayhem.
Can I tell the debugger to skip assembly code automatically?
In my experience, the vast majority of such assembly code is in VCL or RTL units.
If you compile with "Debug .dcu's" disabled then the debugger will not step through this code. However, it will also not step through any other VCL/RTL code either - assembler or Pascal. It will still step through any code that is not part of the VCL/RTL, assuming you have the Debug information option enabled for the project.
Whether turning off VCL/RTL debug units makes debugging any particular issue you may have easier or harder will of course depend on your particular circumstances, but usually what is going on inside the VCL/RTL code is of little consequence unless and until you have eliminated the possibility of some error in your own code and then need to investigate a potential bug in the VCL/RTL itself.
For myself, I have "Debug .dcus" turned OFF unless I need them ON.
Your mileage may vary.
If you see assembler code, you probably are in the Alt-F2 CPU view. Just close the CPU view (escape key on old Delphi, or close its tabs), and you'll continue stepping within pascal source code (e.g. press F7 or F8).
If you see assembler code in the middle of a .pas file (in an asm ... end block), then you can try going to the end of it (at end level) and press F4 (shift F8 is buggy). But be aware that it may quit not at the end but in an internal ret assembler op code. So my personal advice is, if you do not know about assembler, to display the Call Stack (this window displays the function calls that brought you to your current program location and the arguments passed to each function call) and double-click on the parent caller. This will be always safe.
For additional info about debugging, this e.g. this article.
You can use the {$D-} directive to switch off debugging for a block of code. I think this will allow you to achieve what you want.
Also - dont use shift F8 in assembly code, I believe it causes all sorts of trouble - better to place your cursor after the block and F4 down to that.
From time to time I lose breakpoint functionality in Delphi.
I thought this to be a Delphi 2009 issue but now I have also it in Delphi XE.
In Delphi 2009 by deleting .dproj file I made the breakpoints work again.
In Delphi XE I am not able to make breakopints appear. I have update 1 with all hotfixes applied.
Does anyone have a solution?
Debug info isn't present in the file.
Make sure that you're using the Debug configuration. (Project Manager tree, expand Build Configurations, make sure Debug is bold. If it's not, right click Debug and choose Activate from the context menu.) Make sure you then do a Build of your project, not just a Compile.
If that still doesn't work, go to Project->Options from the IDE's main menu, click on Compiling under Delphi Compiler, and check the Debugging section on the right half of the window. Make sure that Debug Information and Local Symbols are both checked. If you're trying to trace into the VCL's own source, also check Use debug .dcus (you'll want to turn this off and do a full build of your project as soon as you're done, as it gets annoying when you're debugging normally). Again, you'll want to build and not compile.
If all of the above fails, another possibility is that the code unit you have open in the Code Editor isn't the same one being seen by the compiler. Make sure you don't have multiple copies of the file on your computer in a location that the compiler might find first. If you're not sure, delete the .dcu files with that unit name and then do a build of your project, and see if the newly created .dcu is in the location you'd expect.
I found a better way.
From the Project Manager tree, right click on the project and choose "Clean" from the popupmenu.
The breakpoints reappear magically and it is a very fast method.
I suspect this happens when you have done a release build, with debug disabled. Then you switch back to debug configuration and do a compile rather than a build. The files where you can't set breakpoints correspond to those with DCUs produced by a compile with debug disabled.
Simply doing a build to re-generate all DCU files will make your breakpoints work again.
Here's one more reason to misaligned code vs breakpoint markers (blue/red "pill" in the gutter).
The editor recognices three different line endings,
CRLF (Carriage Return - Line Feed pair)
CR only
LF only
Of these, CRLF is the default in the editor.
The compiler however, doesn't seem to consider CR only as a line ending, only CRLF and LF only. Thus if your source file happens to have one or more CR only, the "blue pills" will be offset from the source.
You might have got source files with CR only EOL (end of line) character from e.g. the internet. I recall MAC OS used CR only as EOL.
To verify the EOL's in your file, you can turn on the displaying of EOL's in the editor
( Tools - Options - Editor options - Source options - Show line breaks).
The symbols look weird (see images below), but are just C on top of L for CRLF, C on top of R for CR and L on top of F for LF.
The following images show the normal EOL's (CRLF) and the EOLS's after I forced CR only for one line and LF only for another line in a hex editor. As said above, it is the CR only that offsets the break point markers from the source code.
Normal CRLF EOL's:
One line with CR only and one with LF only:
Fix
To reset all EOL's to CRLF, untick Preserve line ends in Editor Options
( Tools - Options - Editor options),
make a trivial change, so that the file is marked as modified, close the file, save changes to XYZ.pas? YES, and reopen.
Now all line endings are CRLF. Rebuilt the project and all the breakpoint balls will be in the correct locations.
Turning on remote debugging symbols did it for me (nothing else worked). Project > Options > Linking and check Include remote debug symbols.
I had the same problem with XE4. This is why I found this article a couple of hours ago. None of the above solutions worked for me. The correct solution for me - up to now - was to add "remote debug symbols" option. Strange because I don't use remote debugging. Anyway it looks OK now.
It is a bug, restarting Delphi will fix your problem.
Try remote debugging to your local PC.
Why it works: (source)
When you debug Delphi projects locally, RAD Studio does not use your RSM debug file because the compiler holds the symbol tables in memory. However, when you debug Delphi projects remotely, you must generate an RSM debug file that contains those symbol tables; otherwise, RAD Studio does not stop at your breakpoints.
Of course, you must first configure your project's "Linking" option "Map file" to "Detailed" to generate the *.rsm file. See Overview of Remote Debugging for how to get started.
I had a related problem: I lost the breakpoints in a particular file, but the other files were fine. What had happened was that I had renamed that file, but unknown to me the DCU for the old file was still being used because it was being referenced in a "uses" clause somewhere.
The solution is to manually delete all the DCUs (doing a "clean" is not enough because the old file represented by the DCU is no longer in the project) and rebuild. You will get a compile error showing the bad "uses" clauses.
Another reason for not working breakpoint could be (often tested with delphi5):
Too many procedures in a unit.
The solution is to move procedures to another unit
Although this is an old question I can confirm that this is still an issue in the current version of Delphi 10.3 Rio.
The answer above regarding line endings
https://stackoverflow.com/a/53360447/6445054
Solved the issue for me I had imported some very old Delphi code which had CR line endings
in a couple of places, as soon as I started moving code around the debugging broke completely.
The option to turn line endings on has moved slightly in Rio it's now
( Tools - Options - Editor - Source - Show line breaks).
In delphi 7 there seems to be a real bug on setting breakpoints.
I had a unit where many texts are definied in a
const constname : array[0..x] of record-type = (...);
in interface section, where record-type has some AnsiString items.
In the implementation section there are some procedures.
In some particular cases, when I set a breakpoint anywhere within a procedure, delphi does not stop at it!
Remarks: all options for debugging are set properly (as for F7 causes delphi stop at the "begin" of the program, blue dots are visible in the whole unit the line stays red while executing the app) and all DCUs that have according PAS files were deleted from all of my disks and within all folders, before I did a complete build on the whole project. So no wold files should hang around anywhere.
For testing, I renamed the PAS to another name, never ever used before, and surely nowhere else on any disk, then adapted all sources and recompiled, just to be sure that delphi and I are looking at the same PAS file - but the breakpoints did not work either.
But there another, very weird thing happened: the text consts (!) changed within my executable (not within exe file, but obviously within memory)! Those texts were checked for correctness during program start, and sometimes it complained about errors! Display of the texts in a messagebox showed, that there was changed a sinlge character within that texts, that are defined as const. For test, I tried to assign something to that consts within my code, but, as expected, compiler complained, so it cannot be an ordinary assignment that causes the change of the text. Must be a wrong pointer. Weird.
So, hours of testing followed, looking for any source code that might have set up a wrong pointer that later could cause that change in a text const. I placed the messagebox into the initialization section of the first unit within the chain of unit initialization I was able to edit, but the changed char was already there! Must be changed very early during startup of my application, then!
Finally I figured out, that the char that appeared in my texts always was an $CC - which exactly is the assembler code for INT 3, the code that delphi is using for setting a breakpoint. And when moving a breakpoint within that unit a line up or down, the position of the changed character also moves some chars left or right! And the number of characters the wrong one moved just correlated with the estimated amount of assembler coded bytes the concerned lines needed. Setting two breakpoint in lines near each other, suddenly two characters changed! When removing all breakpoints from that unit, the text remained unchanged!
So there's only one conclusion: delphi itself is changing that texts when trying to set a breakpoint and fails to do so. I was unable to get rid of this bug. None of the tips about re-synching delphi's internal bookkeeping of source and object code files did help me out!
As the concerned unit mainly consisted of {$I} lines between multiple {$IFDEF}s, for including some different, but long pascal texts, I considered delphi having problems on too long inclusions or on evaluation of conditional compiler directives. So I removed the includes and put the source text immediately into the unit, and removed the {$IFDEF}s - which compiled without errors, but setting breakpoints also changed my text constants, instead of stopping execution. All the same!
I solved this for now by splitting the unit into two units, one holding just the text consts in it's interface part, and a second one to hold the procedures. And now, without changing any compiler nor linker settings, all breakpoints do work like expected and not text is changed any more!
So, if breakpoints do not work for you, while you are sure they should, possibly delphi is the culprit and fails to set the breakpoints at the correct place. In case of it is changing just some texts, maybe that never gets to your attention. Splitting the unit helped me out, maybe that helps you, too.
If the file you're trying to set breakpoints in is part of a DLL, you need to make that DLL active by double-clicking on it in Project Manager so it turns bold, and then build it. Then the blue circles will show up next to lines where you're allowed to set breakpoints.
I solved my issue by making sure Debug was set to Local:
In my case, I was setting breakpoints in a unit that whilst open in the IDE was not part of the currently active project. Such breakpoints also show as green. IOW I was not on the right page at all.
(I discovered this after trying all of the above .)
If the project group uses packages (BPLs) ensure that none of them have any compiler warnings regarding implicitly imported units. If these exist you will only be able to step through the code via the CPU debug window.
Bit late answer but I stumbled on this problem too.
If I activated the MyPackage.bpl (bold) in the project manager with the debug configuration, then compiled it, I could see the IDE registered the debug information (blue dots on left of editor).
But when I activated my MainProject.exe (the one using MyPackage.bpl), those blue dots would disappear, indicating that the debug information is no longer present. After some head scratching, I realized that I did set up a dependency (right click on MainProject.exe -> Dependencies) on the Release configuration of MyPackage.bpl and not on the Debug configuration.
Each time I compiled MyProject.exe, it would link with the Release configuration, not the debug configuration!
So check your dependency configurations!
I had MSBuild checked under Delphi Compile (we do MS Builds). That was preventing breakpoints from working. Unchecked and it works.
By using F9 to run the app, breakpoints will work as expected. I am using XE4 and I do not know if this will "fix" prior versions of Delphi.
Since this is the best resource I found on this issue when encountering this problem with a new install of Delpi XE on a new laptop, I will just add in one more possible answer for Delphi XE.
If you are using a two monitor setup and the code editor window is on the 2nd monitor, the tooltips will not show. Works fine if the editor window is on the primary monitor. Very frustrating. May be a driver issue.
Whenever I rebuild my application and try to step into a break-point the CPU window always appears. From what I understand the CPU window appears when DCU does not match up with the source file, however, in my case the DCU's are defintely being re-compiled and there are no old ones lying around or anything like that.
The strange thing here is if I close down the application and re-open the project, place the breakpoint and run it works fine. I can even modify files and just press F9 to run the project and it works fine....it only seems to be when I rebuild the project (via IDE Project menu or the project context menu) that this CPU window never breaks into the source (even though it can find it!).
I also noticed in the callstack a unit called Generics is always the top of the stack, never the unit my break point is in, this is no way related to where my break point is.
Any ideas?
Try checking your Delphi event log.
Sometimes Windows itself will write an OutputDebugString and then trigger a breakpoint when your application has done something very bad, e.g.:
HEAP[Project1.exe]: HEAP: Free Heap block 32959a8 modified at 32959c0 after it was freed
Windows has triggered a breakpoint in Project1.exe.
This may be due to a corruption of the heap, and indicates a bug in Project1.exe or any of the DLLs it has loaded.
The output window may have more diagnostic information
It can also be Application Verifier (if you're using it; if you're not you should) telling you about a problem.
Here I found suggestion to check Ignore non-user breakpoints in Debugger Options (D2009).