C++ 将unsigned char*buffer强制转换为可以接受参数的可调用void指针
我的问题是,我不知道如何正确地进行铸造,我的目标是调用将放置在buf中的方法 这是我的编译器错误 错误:“buf”不能用作函数 这是我当前的代码C++ 将unsigned char*buffer强制转换为可以接受参数的可调用void指针,c++,c,C++,C,我的问题是,我不知道如何正确地进行铸造,我的目标是调用将放置在buf中的方法 这是我的编译器错误 错误:“buf”不能用作函数 这是我当前的代码 ... unsigned char *getFileBuffer(const char filename[], long &fileSize) { ... } void (*ptrox)(int &) = NULL; int main() { long filesize = -1; int x = 3;
...
unsigned char *getFileBuffer(const char filename[], long &fileSize)
{
...
}
void (*ptrox)(int &) = NULL;
int main()
{
long filesize = -1;
int x = 3;
//buf will consist of a operation, that takes an referenced int as an argument.
unsigned char *buf = getFileBuffer("foo", filesize);
//This is obviously not correct and does not match the description.
ptrox = (void *)&buf(int &);
ptrox(x);
cout << x;
}
正确的类型转换如下所示:
ptrox = (void (*)(int &))buf;
void * libhandle = dlopen("foo.so", RTLD_NOW);
if (!libhandle) {
perror("dlopen");
abort();
}
ptrox = (void (*)(int &))dlsym(libhandle,
"foo" // C function name (use extern "C" where appropriate)
);
if (!ptrox) {
perror("dlsym");
abort();
}
为什么不使用dlopen
/dlsym
加载函数?将不那么容易出错。此外,默认情况下,加载函数的内存将不可执行,因此如果尝试运行ptrox
,它将得到SIGSEGV
为了使用libdl
,您需要在共享库中编译函数foo
,并按如下方式加载:
ptrox = (void (*)(int &))buf;
void * libhandle = dlopen("foo.so", RTLD_NOW);
if (!libhandle) {
perror("dlopen");
abort();
}
ptrox = (void (*)(int &))dlsym(libhandle,
"foo" // C function name (use extern "C" where appropriate)
);
if (!ptrox) {
perror("dlsym");
abort();
}
如果需要加载一个C++函数指针,那么需要使用它的函数名。请咨询nm foo.so
如何mmap
可执行内存:
void * getFileBuffer(const char filename[], long fileSize) {
int fd = open(filename, O_RDONLY);
if (fd < 0) {
perror("open");
abort();
}
void * buf = mmap(
NULL
, fileSize
, PROT_READ | PROT_EXEC
, MAP_PRIVATE
, fd
, 0
);
if (buf == MAP_FAILED) {
perror("map");
abort();
}
return buf;
}
void*getFileBuffer(常量字符文件名[],长文件大小){
int fd=打开(仅文件名);
如果(fd<0){
佩罗(“公开”);
中止();
}
void*buf=mmap(
无效的
,文件大小
,PROT_READ | PROT_EXEC
,MAP_PRIVATE
,fd
, 0
);
if(buf==MAP_失败){
佩罗(“地图”);
中止();
}
返回buf;
}
对我来说,以下构造工作:
ptrox=(void(*)(int&)buf代码>但不知道为什么需要围绕*的偏执
我通常如何处理这个问题:
typedef void *pfunc(int &);
那我可以用
ptrox = (pfunc)buf;
你需要C还是C++的答案,因为它会不同。请C++,但是如果你能提供一个解释,它们之间的差别会很大。括号是用的,所以<代码> */COD>不会被误解为返回类型的一部分(<代码>空白* <代码>)。实际上,您可能也应该将它们与typedef
一起使用。这种转换是有条件支持的(C++11),或者是非法的(早期版本的C++)。在实践中,这通常是(非法)允许的,但通常不能保证指向函数的指针与指向数据的指针大小相同。该死,在typedef上忘记了它们,但对我来说,在typedef上更有意义,它说pfunc是指向函数的指针,(包含标识符和*)。文件“foo”只包含二进制指令,我的计划是尝试将一个方法注入到运行和修改x的程序中。除了此强制转换是非法的之外,至少在C++11之前的版本中是非法的(并且仅在C++11中有条件支持)。正确的赋值方法是*(void**)(&ptrox)=dlsym(libhandle,“foo”)代码>。同样的技术可以用于最初请求的强制转换,但在这种情况下,请注意,它可能无法在所有平台上正常工作(函数指针和数据指针的大小可能不同)。(Posix要求它工作。)@Ogelami在这种情况下,请确保包含加载的二进制指令的内存是可执行的。请注意,在大多数现代系统中,内存不能同时可写和可执行。我仍然建议使用动态加载程序以提高可移植性。哦,我真的不知道它不能同时是可写/可执行的。@Ogelami它可以是可读的和可执行的,但通常操作系统会拒绝同时使内存可写和可执行,以避免某些类型的攻击。