如何通过C语言指针修改函数?该操作是否可行?以及如何实现调用不同函数输出相同结果?
嘿,这个问题问到了C语言里比较底层的内存和函数指针知识点,我来给你详细梳理下:
一、通过C语言指针修改函数本身:可行吗?
答案是:理论上在特定环境下可能实现,但这是强烈不推荐的未定义行为,绝大多数场景下完全没必要这么做。
原因在于:
- 编译后的函数代码默认会被放在程序的只读内存段(比如Linux下的
.text段),操作系统会对这个区域设置写保护。如果你尝试直接通过指针修改这里的内容,会触发内存访问错误(比如Segmentation fault段错误)。 - 即使你通过操作系统API修改了内存段的权限(比如Linux下用
mprotect开启可写),这种操作也属于极度hack的做法:它破坏了程序的内存安全性,代码的可移植性为0,还可能被编译器优化(比如函数内联、常量折叠)彻底打乱你的预期,导致不可预测的结果。
二、你的目标:调用不同“入口”输出相同结果的正确实现
你描述的步骤其实走进了一个误区——根本不需要拷贝函数内存就能实现类似需求。如果你的核心目标是让不同的指针调用后输出相同结果,直接用函数指针绑定同一个函数即可,这是C语言标准允许的安全做法。
正确实现示例
#include <stdio.h> // 定义两个不同的函数(先按你的需求来) void func1() { printf("Hello from func1!\n"); } void func2() { printf("Hello from func2!\n"); } int main() { // 定义函数指针,类型要和目标函数匹配 void (*ptr1)() = func1; void (*ptr2)() = func2; // 现在让ptr2也指向func1,这样调用两个指针结果相同 ptr2 = ptr1; // 调用测试 ptr1(); // 输出:Hello from func1! ptr2(); // 输出:Hello from func1! return 0; }
如果你非要尝试“拷贝函数内存”(仅作知识演示,禁止在生产代码中使用)
假设你在Linux环境下,并且愿意承担风险,以下是一个极端的示例(注意:这是未定义行为,不同编译器/系统可能完全无法运行):
#include <stdio.h> #include <string.h> #include <sys/mman.h> #include <unistd.h> // 定义两个函数 void func1() { printf("I'm func1\n"); } void func2() { printf("I'm func2\n"); } int main() { // 获取内存页大小 size_t page_size = getpagesize(); // 计算func2所在的页起始地址 void* func2_page = (void*)((unsigned long)func2 & ~(page_size - 1)); // 修改func2所在页的权限为可读写可执行(危险操作!) if (mprotect(func2_page, page_size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { perror("mprotect failed"); return 1; } // 拷贝func1的代码到func2的内存区域(假设两个函数长度相同,这也是不可靠的) memcpy(func2, func1, 16); // 16是随便写的长度,实际函数长度很难确定 // 调用测试 func1(); // 输出:I'm func1 func2(); // 可能输出:I'm func1(也可能崩溃或出现其他问题) return 0; }
这个示例的问题非常多:
- 你无法准确获取函数的实际长度,
memcpy的长度完全是瞎猜的,很可能拷贝多了或少了。 - 编译器可能会对函数做优化(比如内联、代码重排),导致你拷贝的代码根本不是实际执行的代码。
- 修改内存权限会带来严重的安全漏洞,恶意代码可以利用这个区域执行任意指令。
总结
- 不要尝试修改函数本身的内存,这是既危险又不必要的操作。
- 如果想让不同的调用入口输出相同结果,直接使用函数指针指向同一个函数即可,这是标准、安全且可移植的做法。
内容的提问来源于stack exchange,提问作者Fantety
相关产品推荐
相关产品推荐

