What about the runtime state of the program? If you make a
catastrophic change (say, replacing an editor with a casino app or
vice versa), I don't see how you can possibly "continue" or what
that would even *mean*. You can "edit-compile-and-start-the-run-over",
which pretty much any debugger can do. But that's not "continue".
I'm not sure what you mean by "replacing an editor with a casino app or
vice versa", but edit-and-continue will make your changes for your and
will adjust the instruction pointer intelligently when it can, and it
will position it incorrectly at other times. In those cases you have to
be cognizant enough to recognize what just happened and correct it, or
simply restart your debugger session and begin again.
Most changes edit-and-continue are used for are these kind:
if (foo) {
// Do something
}
Which should've been:
if (!foo) {
Or:
if (foo and faa) {
Etc. In such cases, you simply make the change, apply changes, reset the
instruction pointer to the test (if need be), and continue on.
Edit and continue also lets you write a lot of code. You can modify the
body of a function, add new functions, do a lot. Microsoft's implementation
is not invincible though. In fact, it's not even bullet proof.
It
is resilient, but it does have limits. The compiler will tell you that it
was unable to apply the change if it can't do so mechanically. But even
in those cases where it can mechanically complete the change, the developer
must be aware enough of the nature of the change to realize that the prior
data being tested is no longer valid, etc., requiring a restart.
If you delete the function where the program is currently running,
*WHERE* does it "continue"?
The instruction pointer is highlighted in Microsoft's Debugger, so you
can see where it went. There's also a call stack window which will show
you where it is. If you delete enough code that it cannot automatically
position the instruction pointer, you're often in a state which requires
a restart. In the alternative, just right-click on the line you want
and choose the "Set next statement" option from the menu.
Does "continue" mean "start over and go full speed to the point
where you stopped the program"?
That's Restart.
If so, does it replay user input
(just about any GUI must have one mouse click per loop) with all
of the timing kept intact?
No.
Mouse input is one of those things it's
almost impossible to re-do exactly, especially if the code saves
time-stamps of every click or mouse movement. And what happens if
"the point where you stopped the program" no longer exists in the
new code?
When you do a restart you've stopped the prior instance, unloaded the
program from memory, and restarted by loading the new program. All of
the new features will be available as you setup breakpoints, etc.
This is completely unresponsive as to what happens to the
*SAVED PROGRAM STATE* that it continues *FROM*. It's easy to
recompile and make the source and object match.
You can do that with edit-and-continue as well. You don't have to use
it. In fact, it's a command line option that the Visual Studio IDE
enables by default when you create a new project (presumably because it
is so useful and popular). However, you don't have to use it. The
option is called "Program Database for Edit-and-continue" and it is one
of the several options. The next option is just "Program Database"
which will reveal source code information, but it will not allow edit-
and-continue changes, but just runtime information about the running
program (as with traditional debuggers).
That doesn't make it easy to fix huge data structures in memory
that have all been mangled because of an initial mistake in generating
those data structures. Here you may WANT "edit-and-start-over".
As is true today, if the change was major enough you can always Restart.
When you restart it physically terminates the prior running program, does
any post-termination linking to permanently apply any code changes made
under edit-and-continue to the static object file, and then restarts a
new running instance.
I can see where it is easy to stop the program, change some values
of variables, (for which there may be no corresponding source change
since the value you are changing is not an initial value), and
continue. I do not see how it would be possible to stop on buffer
overflow, redeclare a char array to be of size 1024 rather than 80,
and then continue, especially a C program written in "pointers
galore" style where trying to relocate an already overflown buffer
will be a problem because of all the pointer variables pointing at
it..
Suppose your source line is:
char* foo = malloc(80);
And you realize that this buffer is too small. You can modify that souce
code to be:
char* foo = malloc(1024);
You set the instruction pointer back up to that line, execute the one line,
which now gives you a new pointer to 1024 bytes of memory, then set the
instruction pointer back to where it was and continue on with the larger
buffer.
You can also write little fixups in your code. Suppose you want to copy the
first 80 bytes. Instead of making the change above, make this change:
char* foonew = malloc(1024);
memcpy(foonew, foo, 80);
foo = foonew;
After you execute those three lines, delete the extraneous ones, and you've
never had to leave your runtime environment, and you can continue debugging.
Edit-and-continue helps in a lot of areas, but it's not perfect. It depends
largely on what type of program you're writing. If you have one that uses
a lot of logic tests, then it may be of great benefit because you can fixup
those easily and continue running. If it's a lot of computed data, then
it won't be of much use most likely (because the data has to be regenerated
using the new algorithm, and that is easier with a restart).
I plan for my edit-and-continue abilities to allow every change mechanically.
I do not plan to put any limits on the code changing abilities. Things that
go out of scope will simply remain as now stale variables, and so on.
However, there will still be limits in my implementation as per the nature
of the data being processed. In some cases you could write little fixup
code snippets, run those, and then delete them (as the sample above with
foonew). But, even in those cases it may be faster or easier to Restart.
It will depend on many factors, and that's what the developer needs to be
aware of (to choose for himself).
Best regards,
Rick C. Hodgin