将函数写入二进制文件?

时间:2016-12-23 06:47:35

标签: c++ function file io binary

让我相当好奇的是,因为在C ++中可以在正确的情况下将函数作为参数传递,这表明无论内部代码处理该函数都可以指向并以其他方式写入并读入二进制文件作为其可执行代码。

这显然是来自某人,而我可能有很强的C ++背景,我不熟悉复杂的内部结构,关于如何在堆中管理内​​存,尤其是可执行机器代码如何适应图片。 / p>

我假设因为可以传递对函数的引用,所以可以获取它指向的数据并将其写入某处。我不知道。

有人想告诉我这是否可行?如果是这样,你能举个例子吗?如果没有,请告诉我原因!我喜欢更深入地了解C ++如何实际在内部工作。

3 个答案:

答案 0 :(得分:2)

20年前,您的建议可能是新的和可用的。人们通过按需从文件加载代码,然后调用它然后卸载来节省内存。这被称为叠加。在某种程度上它是可用的,但是在平台和平台标准化的形式中,API管理它。 共享库(在POSIX系统中的.so,在Windows中的.dll)背后的机制是库的文件包含某些功能的标签,它们的名称,以及有关如何初始化堆栈和数据段的数据。当程序加载时,它可以由系统自动完成。否则,您可以手动加载库并加载指向函数的指针。例如。在Windows上,由Linux上的LoadLibrary()和GetProcAddress(),dlopen()和dlsym()组成。

为什么现在不可能使用高级语言:安全性,防止数据段中的恶意代码。运行时库通常会处理它。 仍然可以使用汇编程序,但您将挑战防病毒和系统安全措施。通过仔细编程,您可以创建自己的"链接器"我想,能够创建自己的库并加载。

答案 1 :(得分:1)

不,你真的不能这样做。有很多原因,但这里有一个简单直观的原因:功能可能会调用其他功能。如果您能够将一个函数写入磁盘并将其恢复,则不会考虑它的依赖关系(它调用的函数,它更新的全局变量等)。它不会工作。

如果你想从磁盘读取函数,最好用Lua这样的脚本语言来表达它们。这是一种经过验证的解决方案,可用于许多商业产品,如视频游戏和Adobe Lightroom。

答案 2 :(得分:0)

虽然函数指针是函数的入口点,并且该内存可以被读取并因此被复制,但第一个问题是没有可靠的方法来确定该代码的长度,因此您无法确定某个< em>要复制多少才能获得整个功能而只有那个。

另一个问题是什么实际结束?根据平台,代码可能无法重定位,并且可以链接到其他代码。二进制文件不包含符号信息;您可以做的最好的事情就是反汇编它,但是在整个链接的可执行文件的上下文中,这样做可能不是很有用。

如果您的目标是将功能与主要可执行文件分开,并且以后能够加载和运行它们,那么这就是DLL和共享库的用途。

如果您只想观察与函数相关的二进制文件,那么最好在调试器中完成 - 它将具有反汇编视图模式,该模式将显示原始二进制文件(十六进制),带符号链接的汇编代码和对应的C源。如果您的目标仅仅是研究源代码与二进制机器代码的关系,那么这就更有意义了。

以下是你可能做的事情 - 即使没有实际的理由这样做。它假设编译器的行为在某些情况下可能无效。例如,它假设编译器将相邻函数连续放在内存中并增加内存地址,以便function2在内存中 function1之后立即。此处function2仅用作function1的结束标记,可能是虚拟的。

int function1()
{
    ...

    return 0 ;
}

void function2() 
{
}

#include <stddef.h>

int main()
{
    ptrdiff_t function1_length = (char*)function2 - (char*)function1 ;

    FILE* fp = fopen( "function1.bin", "wb" ) ;
    fwrite( function1, function1_length, 1, fp ) ;
    fclose( fp ) ;
}