首页 文章

自修改代码

提问于
浏览
30
  • 我最近在考虑编写 self-modifying programs ,我认为它可能是强大而有趣的...所以我目前正在寻找一种允许轻松修改程序自己的代码的语言 .

  • 我读到了 C# (作为一种方式)以及在运行时编译和执行代码的能力,但这太伤人了......

  • 我也在考虑 assembly ...更改运行代码更容易,但它不是很强大(非常原始)......

你能给我一个强大的语言 - 或者一个支持在运行时修改代码的功能吗?

Hints
这就是我在运行时修改代码的意思:

Start:
  a=10,b=20,c=0;
  label1: c=a+b;
  ....
  label1= c=a*b;
  goto label1;

并且可能正在 Build 一份指令清单:

code1.add(c=a+b);
  code1.add(c=c*(c-1));
  code1. execute();

Thanks!

13 回答

  • 0

    到目前为止,每个答案都是关于反射/运行时编译,但在您提到的评论中,您对实际的内容感兴趣的代码感兴趣 .

    在C#,Java甚至(可移植)中无法在C中执行此操作 - 也就是说,您无法使用这些语言修改加载的内存中二进制文件 .

    一般来说,唯一的方法是使用汇编,并且它依赖于高度操作系统:为防止polymorphic viruses,大多数现代操作系统(包括Windows XP,Linux和BSD)强制执行W^X,这意味着你有要go through some trouble在那些操作系统中编写多态可执行文件,以便完全允许它 .

    在某些解释语言中,程序可能会在程序运行时修改自己的源代码 . Perl,Python(参见here),以及我知道的Javascript的每个实现都不允许这样做 .

  • 4

    Common Lisp的设计考虑到了这种情况 . 您也可以尝试Smalltalk,其中使用反射来修改运行代码并不是未知的 .

    在这两种语言中,您可能会替换整个函数或整个方法,而不是单行代码 . Smalltalk方法往往比Lisp函数更精细,因此这可能是一个好的开始 .

  • 2

    您可以在Maple(计算机代数语言)中执行此操作 . 与上面的许多答案不同,这些答案使用的编译语言只允许您在运行时创建和链接 new 代码,在这里您可以诚实地改善当前正在运行的程序的代码 . (Ruby和Lisp,正如其他回答者所指出的那样,也允许你这样做;也可能是Smalltalk) .

    实际上,它曾经是Maple的标准,大多数库函数都是小的存根,它们会在第一次调用时从磁盘加载它们的“真实”自身,然后自我修改自己到加载的版本 . 由于库加载已虚拟化,因此不再是这种情况 .

    正如其他人所指出的那样:你需要一种具有强烈反思和具体化设施的解释语言来实现这一目标 .

    我为Maple代码编写了一个自动规范化器/简化器,我继续在整个库(包括它自己)上运行;因为我在所有代码中都不太谨慎,所以规范化程序确实修改了自己 . 我还写了一个名为MapleMIX - available on sourceforgePartial Evaluator(最近被SCP接受) - 但是它不能完全适用于它自己(这不是设计目标) .

  • 0

    Malbolge将是一个很好的起点 . 每条指令都是自我修改的,玩起来很有趣(*) .

    (*)免责声明:实际上可能并不好玩 .

  • 2

    我编写了Python类Code,它允许您向对象添加和删除新的代码行,打印代码并执行它 . 类代码最后显示 .

    示例:如果x == 1,则代码将其值更改为x = 2,然后使用检查该条件的条件删除整个块 .

    #Initialize Variables
    x = 1
    
    #Create Code
    code = Code()
    code + 'global x, code' #Adds a new Code instance code[0] with this line of code => internally             code.subcode[0]
    code + "if x == 1:"     #Adds a new Code instance code[1] with this line of code => internally code.subcode[1]
    code[1] + "x = 2"       #Adds a new Code instance 0 under code[1] with this line of code => internally code.subcode[1].subcode[0]
    code[1] + "del code[1]" #Adds a new Code instance 0 under code[1] with this line of code => internally code.subcode[1].subcode[1]
    

    创建代码后,您可以打印它:

    #Prints
    print "Initial Code:"
    print code
    print "x = " + str(x)
    

    输出:

    Initial Code:
    
    global x, code
    if x == 1:
        x = 2
        del code[1]
    
    x = 1
    

    通过调用对象执行cade:code()

    print "Code after execution:"
    code() #Executes code
    print code
    print "x = " + str(x)
    

    输出2:

    Code after execution:
    
    global x, code
    
    x = 2
    

    如您所见,代码将变量x更改为值2并删除整个if块 . 这可能有助于避免在满足条件后检查条件 . 在现实生活中,这种案例场景可以由协程系统处理,但这种自我修改代码实验只是为了好玩 .

    class Code:
    
        def __init__(self,line = '',indent = -1):
    
            if indent < -1:
                raise NameError('Invalid {} indent'.format(indent))
    
            self.strindent = ''
            for i in xrange(indent):
                self.strindent = '    ' + self.strindent
    
            self.strsubindent = '    ' + self.strindent
    
            self.line = line
            self.subcode = []
            self.indent = indent
    
    
        def __add__(self,other):
    
            if other.__class__ is str:
                other_code = Code(other,self.indent+1)
                self.subcode.append(other_code)
                return self
    
            elif other.__class__ is Code:
                self.subcode.append(other)
                return self
    
        def __sub__(self,other):
    
            if other.__class__ is str:
                for code in self.subcode:
                    if code.line == other:
                        self.subcode.remove(code)
                        return self
    
    
            elif other.__class__ is Code:
                self.subcode.remove(other)
    
    
        def __repr__(self):
            rep = self.strindent + self.line + '\n'
            for code in self.subcode: rep += code.__repr__()
            return rep
    
        def __call__(self):
            print 'executing code'
            exec(self.__repr__())
            return self.__repr__()
    
    
        def __getitem__(self,key):
            if key.__class__ is str:
                    for code in self.subcode:
                        if code.line is key:
                            return code
            elif key.__class__ is int:
                return self.subcode[key]
    
        def __delitem__(self,key):
            if key.__class__ is str:
                for i in range(len(self.subcode)):
                    code = self.subcode[i]
                    if code.line is key:
                        del self.subcode[i]
            elif key.__class__ is int:
                del self.subcode[key]
    
  • 12

    我强烈推荐Lisp . Lisp数据可以作为代码读取和执行 . Lisp代码可以写成数据 .

    它被认为是规范的自我修改语言之一 .

    示例列表(数据):

    '(+ 1 2 3)
    

    或者,将数据称为代码

    (eval '(+ 1 2 3))
    

    运行该功能 .

    您还可以即时进入并编辑列表成员 .

    编辑:

    我编写了一个程序来动态生成一个程序并在运行中对其进行评估,然后向我报告它与基线相比如何(div为0是通常的报告,ha) .

  • 20

    Lua中,您可以"hook"现有代码,它允许您将任意代码附加到函数调用 . 它是这样的:

    local oldMyFunction = myFunction
    myFunction = function(arg)
        if arg.blah then return oldMyFunction(arg) end
        else
            --do whatever
        end
    end
    

    您还可以简单地使用函数,这样可以自动修改代码 .

  • 1

    许多语言允许您在运行时使用eval代码 .

    • Lisp

    • Perl

    • 蟒蛇

    • PHP

    • Ruby

    • Groovy(通过GroovyShell)

  • 42

    我有时候,虽然很少在Ruby中使用自修改代码 .

    有时你有一种方法,你不知道你正在使用的数据(例如一些惰性缓存)是否正确初始化 . 因此,您必须在方法的开头检查数据是否已正确初始化,然后可能将其初始化 . 但是你真的只需要进行一次初始化,但每次都要检查它 .

    因此,有时我会编写一个执行初始化的方法,然后将其自身替换为不包含初始化代码的版本 .

    class Cache
      def [](key)
        @backing_store ||= self.expensive_initialization
    
        def [](key)
          @backing_store[key]
        end
    
        @backing_store[key]
      end
    end
    

    但老实说,我不值得 . 事实上,我很尴尬地承认我从来没有真正进行过基准测试,看看这个条件是否确实有所不同 . (在现代Ruby实现中,可能没有积极优化配置文件反馈驱动的JIT编译器 . )

    请注意,根据您定义"self-modifying code"的方式,这可能是您想要的,也可能不是 . 您正在替换当前正在执行的程序的某些部分,因此......

    编辑:现在我考虑一下,这种优化没有多大意义 . 昂贵的初始化只会执行一次 . 修改唯一避免的是有条件的 . 最好以支票本身价格昂贵为例,但我想不出一个 .

    但是,我想到了一个很好的自修改代码示例:Maxine JVM . Maxine是一个研究虚拟机(技术上实际上不允许被称为"JVM",因为它的开发人员不运行兼容性测试套件)完全用Java编写 . 现在,有很多JVM都是自己编写的,但Maxine是我所知道的唯一一个也可以运行的JVM . 这非常强大 . 例如,JIT编译器可以JIT编译自身以使其适应JIT编译的代码类型 .

    Klein VM中发生了类似的事情,它是自编程语言的VM .

    在这两种情况下,VM都可以在运行时优化和重新编译 .

  • 8

    就个人而言,我发现很难找到比C#更易于处理的程序集 . 我觉得你认为装配不是那么强大就更奇怪了:你不能比原始机器语言更强大 . 无论如何,对他/她自己 .

    C#有很好的反射服务,但是如果你对此有厌恶 . 如果你对C或C非常熟悉,你总是可以编写一个编写C / C并将其发送给编译器的程序 . 只有当您的解决方案不需要快速的自我重写周转时间(大约几十秒或更长时间)时,这才是可行的 .

    Javascript和Python都支持反射 . 如果您正在考虑学习一种新的,有趣的编程语言,这种语言功能强大但技术要求不高,我建议使用Python .

  • 7

    在运行时编译和执行代码的高级语言中,它不是真正的自修改代码,而是动态类加载 . 使用继承原则,您可以替换类Factory并在运行时更改应用程序行为 .

    只有在汇编语言中,您才真正通过直接写入代码段进行真正的自我修改 . 但它没有什么实际用途 . 如果您喜欢挑战,请编写自加密,可能是多态病毒 . 这应该很有趣 .

  • 6

    你看过Java吗? Java 6有一个compiler API,因此您可以编写代码并在Java VM中编译它 .

  • 9

    我可以建议Python,这是一个非常高级的动态语言,包含丰富的内省(例如,使用 compileevalexec 允许一种自修改代码) . 一个基于您的问题的简单示例:

    def label1(a,b,c):
        c=a+b
        return c
    
    a,b,c=10,20,0    
    print label1(a,b,c) # prints 30
    
    newdef= \
    """
    def label1(a,b,c):
        c=a*b
        return c
    """
    exec(newdef,globals(),globals())
    
    print label1(a,b,c) # prints 200
    

    请注意,在上面的代码示例中, c 仅在函数范围中更改 .

相关问题