我知道了一种使用__FILE__宏在C中打印正在运行的代码的源代码的方法.因此,我可以寻找位置并使用putchar()来改变文件的内容.
是否可以使用此方法动态更改正在运行的代码?
是否可以使用此方法动态更改正在运行的代码?
不,因为一旦编译了一个程序,它就不再依赖于源文件了.
如果您想了解如何更改已在流程内部运行的流程的行为,您需要了解正在使用的体系结构的组装,系统上的可执行文件格式以及您的流程API.系统,至少.
正如大多数其他答案所解释的那样,实际上,大多数 C 实现都是编译器。因此,正在运行的可执行文件与源代码只有间接(且延迟)的关系,因为源代码必须由编译器处理才能生成该可执行文件。
请记住,编程语言是(不是软件,而是......)一种规范,写在一些报告中。阅读n1570 , C11的规范草案。大多数 C 实现都是命令行编译器(例如自由软件领域的GCC和Clang/LLVM),即使您可能会找到解释器。
但是,对于某些操作系统(特别是 POSIX 操作系统,例如 MacOSX 和 Linux),您可以动态加载一些插件。或者您可以以其他方式(例如libgccjit或LLVM或libjit或GNU lighting等JIT 编译库)创建一个新函数并动态获取指向它的指针(这并不严格意义上符合 C 标准,其中函数指针应该指向程序的某个现有函数)。
在Linux上,您可能会在一些临时源文件中生成(在您自己的程序的运行时,链接以-rdynamic使其名称可从插件中使用,并使用-ldl库来获取动态加载程序)一些C代码/tmp/gencode.c,运行编译(使用例如系统(3)或popen(3)/tmp/gencode.so )通过命令将发出的代码作为插件,例如 例如 ,然后使用dlopen(3)
gcc -O1 -g -Wall -fPIC -shared /tmp/gencode.c -o /tmp/gencode.so动态加载该插件,使用dlsym(3在加载的插件中查找函数指针(来自一些常规名称)),并间接调用该函数指针。我的Manydl.c程序显示,对于数十万个生成的 C 文件和加载的插件来说,这是可能的。我在GCC MELT中使用了类似的技巧。另请参见这个和那个。请注意,您并没有真正“自我修改”C 代码,您更广泛地生成额外的C 代码,编译它(作为某些插件等......),然后加载它 - 作为扩展或插件 - 然后使用它。
(出于实用原因,包括易于调试,我不建议覆盖一些现有的 C 文件,而只是在一些新的临时.c文件中发出新的 C 代码 - 来自一些内部AST类似的表示 - 您稍后将其提供给编译器)
是否可以动态更改正在运行的代码?
一般来说(至少在 Linux 和大多数 POSIX 系统上),机器代码位于虚拟地址空间的只读代码段中,因此您无法更改或覆盖它;但您可以通过函数指针(在 C 代码中)使用间接调用来调用新加载的代码(例如,来自-ed 插件)。dlopen
然而,您也可以阅读有关同形语言、元编程、多阶段编程的内容,并尝试使用 Common Lisp(例如使用其SBCL实现,它在每次REPL交互和每次eval时编译为机器代码)。我还建议阅读SICP(一本优秀且免费的编程简介,其中一些章节与元编程方法相关)
附言。在 Windows 中,使用LoadLibrary也可以动态加载插件(我不知道),但模型非常不同(且不兼容)。阅读 Levine 的链接器和加载器。
| 归档时间: |
|
| 查看次数: |
192 次 |
| 最近记录: |