> This doesn't seem like something that's particularly difficult to do with c/gdb.
Well, why don't you do it, then? Not trying to be snarky(not much anyway), but I feel you are seriously under-estimating the work involved. Either that, or the description does not make it clear enough.
It's a full blown REPL. We are not talking about just printing out the code at that point, or maybe mutating a variable on the stack. We can execute arbitrary code and even replace entire sections of code with new code, and then hit continue and it works as if nothing happened, only now running the new (and hopefully corrected) code. Just the memory management implications of doing this in C would be very interesting.
Note that you can also do this over a network connection. NASA folks used this to great effect to patch Deep Space-1. Lisp machines also used this capability over the entire OS.
I have also used a similar mechanism (with Chicken Scheme) to do incremental development on iOS, without having to do the whole xcode deploy/run cycle.
The closest analog I can think of today is a browser's "console", which lets you do similar things for javascript code.
You can put your code in shared objects and then reload them. Well, I've never done it myself as I haven't seen the need but it seems easy enough, you'd simply have to define a macro for defining functions (you'd just have to write them as FUN(void, bla)(int x, int y) instead of void bla(int x, int y)), which would add the function to a symbol table so then you can say reload("bla") from within gdb and then keep running. I'm not quite sure what you mean by 'the memory management implications of doing this in C would be very interesting'? The only thing, really, that you'd expect to stop working static variables.
You might be interested to read more about this not particularly difficult problem, known in general as "dynamic software updating". You can get a general overview on Wikipedia, but I'd recommend having a browse through the work of Michael Hicks and colleagues: https://www.cs.umd.edu/~mwh/papers/mwh-cat.html
They've worked on a number of iterations on this idea, of which these are probably the most interesting and relevant to C:
There are a few ways in which the shared objects method you suggest does not match the full power of Lisp debugging.
First of all, when a C program crashes, it just crashes. There is no REPL. There is only a core dump. So any live-debugging you plan to do is after the fact. After you have seen a crash, you would now begin to prepare for the next crash by launching your process via GDB or restarting your process and attaching a GDB to it. Whether a similar crash would occur again or not or when it would occur again depends on the nature of the bug. Now contrast this with Lisp debugging when your program crashes, it stops there and offers you an REPL to interact with the program right then. There is no need to wait for the next crash.
Secondly, when you debug with GDB, you would be dealing with syntaxes: The syntax of C that we are so familiar with. The GDB syntax to investigate the problem that we may be less familiar with. When the Lisp debugger offers the REPL to you, you are working with Lisp again. Your compiler, debugger, program, etc. all are part of the same unified environment where you just execute Lisp code to debug your issue.
Finally, putting your code in shared objects and reloading them requires you to go through the complete write-build-test-debug cycle. And then what do you do if your shared object itself crashes? With Lisp you skip the write-build-test part when all you want to do is debug an error. You jump straight to the debug part of the cycle and begin investigating the runtime state. And it works the same in a uniform manner whether your main program crashes or a dependency crashes.
Well, why don't you do it, then? Not trying to be snarky(not much anyway), but I feel you are seriously under-estimating the work involved. Either that, or the description does not make it clear enough.
It's a full blown REPL. We are not talking about just printing out the code at that point, or maybe mutating a variable on the stack. We can execute arbitrary code and even replace entire sections of code with new code, and then hit continue and it works as if nothing happened, only now running the new (and hopefully corrected) code. Just the memory management implications of doing this in C would be very interesting.
Note that you can also do this over a network connection. NASA folks used this to great effect to patch Deep Space-1. Lisp machines also used this capability over the entire OS. I have also used a similar mechanism (with Chicken Scheme) to do incremental development on iOS, without having to do the whole xcode deploy/run cycle.
The closest analog I can think of today is a browser's "console", which lets you do similar things for javascript code.