malloc'中的C函数代码;d存储器

malloc'中的C函数代码;d存储器,c,memory,heap,heap-memory,C,Memory,Heap,Heap Memory,有没有一种方法可以在malloc内存空间中复制函数代码 这个问题在实践中可能没有意义。出于好奇,我提出了这个问题,以便更好地了解c及其底层实现是如何工作的 如果可以将代码复制到堆中,下面是后续问题: 复制时如何确定函数二进制代码的大小 我们可以使用函数指针来执行代码吗?(代码放在malloc的内存中,出于安全原因,该部分内存可能被标记为不可执行,但我对此不确定) 这(或类似的)在大多数机器上都是可能的,但是你使用的技术是系统特有的——没有标准的C或C++的方式来做。 即使计算出一个函数的长度以便

有没有一种方法可以在malloc内存空间中复制函数代码

这个问题在实践中可能没有意义。出于好奇,我提出了这个问题,以便更好地了解c及其底层实现是如何工作的

如果可以将代码复制到堆中,下面是后续问题:

  • 复制时如何确定函数二进制代码的大小

  • 我们可以使用函数指针来执行代码吗?(代码放在malloc的内存中,出于安全原因,该部分内存可能被标记为不可执行,但我对此不确定)

  • 这(或类似的)在大多数机器上都是可能的,但是你使用的技术是系统特有的——没有标准的C或C++的方式来做。 即使计算出一个函数的长度以便可以复制它也很困难。如果函数在同一个翻译单元中,我认为你不能可靠地完成它,因为编译器可能已经完成了你看不到的优化魔术。但是,如果函数位于不同的文件中,那么它的接口可能会更可靠(尽管可能会出现链接器魔术,您必须理解并模仿才能实现目标)

    其他问题(在某些系统上)是malloc的内存可能不可执行。(通常情况下,通过防止执行放在溢出缓冲区中的代码来提高安全性。)但是,具有可执行保护的系统通常具有备用内存分配功能,可以为您提供一块内存,可执行代码可以放置在该内存中,执行可以转移到该内存中。为了实现共享库,此功能的某些变体是必需的

    最后,尽管在考虑您的问题时,人们可能首先想到的是自修改代码,但在本机代码的即时编译系统中可能会合理、合法地使用相关技术

    <>你可以通过指定一个特定的OS和CPU来获得更好的答案。在这里你可以这样做。

    < p>这个(或类似的)在大多数机器上是可能的,但是你使用的技术是系统特定的——没有标准的C或C++的方式来做。 即使计算出一个函数的长度以便可以复制它也很困难。如果函数在同一个翻译单元中,我认为你不能可靠地完成它,因为编译器可能已经完成了你看不到的优化魔术。但是,如果函数位于不同的文件中,那么它的接口可能会更可靠(尽管可能会出现链接器魔术,您必须理解并模仿才能实现目标)

    其他问题(在某些系统上)是malloc的内存可能不可执行。(通常情况下,通过防止执行放在溢出缓冲区中的代码来提高安全性。)但是,具有可执行保护的系统通常具有备用内存分配功能,可以为您提供一块内存,可执行代码可以放置在该内存中,执行可以转移到该内存中。为了实现共享库,此功能的某些变体是必需的

    最后,尽管在考虑您的问题时,人们可能首先想到的是自修改代码,但在本机代码的即时编译系统中可能会合理、合法地使用相关技术

    < >你可以通过指定一个特定的OS和CPU来获得更好的答案。

    < P> C标准(例如,Read)或C++(例如C++ 11、C++ 14,并注意它们已经拥有和更多有关…)不定义函数地址或指针。(它只定义调用这样的地址所做的事情,然后函数指针应该指向现有函数,并且没有标准的方法在运行时动态构建新函数)。在某些系统(纯)中,函数位于不同于C堆的地址空间中(在这些系统上,执行malloc-ed堆中的任何操作都是毫无意义的),因此C11标准禁止将函数指针强制转换为数据指针,反之亦然

    那么,请回答你的问题

    有没有一种方法可以malloc内存空间,然后将函数代码放入C中的空间中

    答案通常是否定的(但在某些系统上,您可以在运行时生成代码,见下文)

    但是,在台式机或笔记本电脑或服务器PC或平板电脑(运行Linux、Windows、MacOSX、Android等常见操作系统)上,通常有一个,并且(对于给定的)有一个共享代码和数据的单一操作系统(尤其是使用
    malloc
    获得的堆数据)。该虚拟地址空间组织在中,每个页面都有自己的。请阅读更多关于,s的信息。堆分配的数据通常无法通过

    操作系统起着至关重要的作用。您需要阅读一整本关于操作系统的书,例如

    (我猜想您想在运行时“创建”程序中的一些新函数,并通过C函数指针调用它们;您应该解释原因;我想您正在为PC或平板电脑编写一些应用程序,使用类似Unix的操作系统,实际上是Linux-x86_64发行版,但您可以将我的答案适应Windows)

    您可以使用一些库,例如,(或GNU),它们生成可执行的代码

    您还可以在某些POSIX系统上使用dynamic,查看&(可用于从加载的插件“创建”函数地址,超出C11标准允许的范围)。一种可能的方法是在临时文件中生成一些C代码,将其编译成插件,然后
    dlopen
    生成该插件。有关更多详细信息,请参阅

    在Linux上,您可以使用和相关(用于在中实现,也可以通过)来更改虚拟地址空间,以及系统调用来更改保护(逐页)