使用基于堆的数据调用以堆栈对象作为参数的函数
我有一个复杂的问题需要解决,因为我陷入困境并且根本找不到解决这个问题的方法。 这是一段代码
struct MyStruct
{
int x;
float y;
char c;
};
void foo(MyStruct a_myStruct);
int _tmain(int argc, _TCHAR* argv[])
{
void *pMyStruct = malloc(sizeof(MyStruct));
int* pInt = (int*)pMyStruct;
*pInt = 10;
pInt++;
float *pFloat = (float*)pInt;
*pFloat = 2.545;
pFloat++;
char *pChar = (char*)pFloat;
*pChar = 'c';
_asm
{
pMyStruct
call foo
}
return 0;
}
void foo(MyStruct a_myStruct)
{
}
,您可以看到 foo
正在对堆栈上的一个对象进行操作,并期望在调用 foo
时映射堆栈对象。但不幸的是, MyStruct
类型在编译时未知,因此我必须创建内存块,然后在运行时将数据填充到该块中,然后在 foo
获取时传递该数据块使用 asm 调用,如上所示。
现在如何将堆空指针转换为堆栈类型对象。不知何故,如果我获得 foo
的 a_myStruct
参数的地址,我可以用 void*
指向该位置,但我又无法取消引用void*
以便将其转换为 MyStruct
类型的对象。
还有其他方法可以解决问题吗?与 C++ 中一样,我们也可以在运行时确定类型。
我在 C++ 运行时调用函数时遇到问题,这些函数可能具有编译时未知的完整用户定义类型的签名。但是这些类型的详细信息对我来说是可用的(当我从类型库中破译某些类型的详细信息时)或来自 DIA SDK)。但现在主要的问题是我想在运行时调用这些函数。在编译时,我只有函数的地址和用户定义类型的详细信息,其中对象或指针作为该函数签名的参数参与。现在,如果我想在运行时调用该函数,我需要首先在运行时通过在堆上创建临时块并用数据填充该块来填充该类型。我拥有该类型的所有详细信息。
现在的问题是我不知道该函数将参数作为我有可用详细信息的类型的指针,或者该参数正是该类型的堆栈对象。如果我有指向该类型的指针,没问题,但如果有对象,我在运行时调用该函数就会遇到很大的问题。
I have a complex problem to be solve, as I am stuck and found no way at all to solve this.
Here's a code
struct MyStruct
{
int x;
float y;
char c;
};
void foo(MyStruct a_myStruct);
int _tmain(int argc, _TCHAR* argv[])
{
void *pMyStruct = malloc(sizeof(MyStruct));
int* pInt = (int*)pMyStruct;
*pInt = 10;
pInt++;
float *pFloat = (float*)pInt;
*pFloat = 2.545;
pFloat++;
char *pChar = (char*)pFloat;
*pChar = 'c';
_asm
{
pMyStruct
call foo
}
return 0;
}
void foo(MyStruct a_myStruct)
{
}
Here you can see that foo
is operating on an object on the stack and is expecting the stack object to be mapped when foo
gets called. But unfortunately the MyStruct
type is not known at compile time so I have to create blocks of memory and then at runtime data is filled within that block which is then passed when foo
gets called with asm as show above.
Now how can I convert a heap void pointer into stack type object. Somehow if I get the address of the a_myStruct
argument of foo
, I can point with void*
to that location but again I can't dereference void*
so that it gets converted into an object of MyStruct
type.
Any other way around to solve the problem? As in C++ we can determine type at runtime as well.
I have a problem to call functions at run time in C++ which might have signature with full of user defined types that are not known at compile time.But details of those types are available to me(As I deciphered details of certain type from type library or from DIA SDK). But the main problem is now i want to call these functions at runtime. At compile time I just have address of function and details of user defined type of which object or pointer is participating as argument of that function signature. Now If i want to call that function at run time, i need to populate that type at runtime first by creating temporary block on heap and filling that block with the data .I have all details of that type.
Now problem is i don't know that function taking argument as pointer of that type of which I have details available or that argument is exactly the stack object of that type. If i have pointer to that type no problem, but if object there i have big problem to call that function at runtime.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不明白为什么您认为需要按照显示的方式填充结构,但无论如何,您都做错了。
它需要更像:
这完全依赖于平台,并且可能也无法正常工作。
假设您填充了 myStruct,调用
foo
的一个简单解决方案是将其更改为:to如果不可能,您需要将其复制到堆栈中。像这样的东西
<罢工>
> <罢工>
可能会起作用。或者不是,因为您在编译时不知道 MyStruct,所以编译器无法生成堆栈操作代码。
我假设您在运行时确实知道 MyStruct 有多大。所以它必须更像这样:
I don't understand why you think you need to populate your struct the way you are showing, but regardless, you are doing it wrong.
It would need to be more like:
Which is completely platform dependent, and probably won't work right either.
Assuming you get myStruct populated, One simple solution to calling
foo
would be to change it to this:toIf that's not possible, you need to copy it to the stack. Something like
might work. Or not, since you don't know MyStruct at compile time, the compiler can't generate the stack manipulation code.
I'm assuming you do know at runtime how big MyStruct is. So it's got to be more like this:
我必须承认,即使您提供了额外的信息,我也不完全理解您的问题。但是让我说一些关于堆栈、堆和 C++ 的一般情况:
如何将参数传递给函数是特定 C++ 编译器的实现细节,即。不同的 C++ 编译器的情况可能有所不同。将参数传递给函数的方法称为调用约定。有些编译器既不使用堆栈也不使用堆来传递参数;相反,如果可能的话,它们会使用 CPU 寄存器。 (Watcom 的 C++ 编译器是/曾经是支持寄存器将参数传递给函数的编译器的一个突出示例。)
这意味着任何 C++ 编译器都可能创建不二进制兼容< /em> 到另一个 C++ 编译器。 (C++ 语言标准没有规定编译输出的二进制标准,因此不同的编译器可能会产生二进制不兼容的输出;但任何 C++ 编译器都保证至少与其自身是二进制兼容的。)因此,如果您想使用库,您有三个选项:
选择与您的特定 C++ 编译器和链接器相匹配的二进制文件;
使用您的编译器自行编译库源代码;或
选择一个遵循特定二进制标准(例如 DLL 库格式或 Microsoft 的 COM 标准)的库二进制文件,您的 C++ 编译器和链接器也支持该标准。
总之,您关于堆栈对象与堆对象的问题没有意义。 C++ 中不存在“堆栈对象”这样的东西。您无法显式控制如何将参数传递给函数,因为这是 C++ 编译器将自行决定如何执行的操作 - 虽然似乎存在关键字和特殊语法来控制此行为(即引用、指针、以及
auto
和register
关键字),它们通常不会向您保证参数将以特定方式传递。如果您很了解某个特定编译器,那么您也许能够推断出参数传递如何与该编译器一起工作......但是通常,您不能并且不必这样做——了解这个机制。PS:我忘了提到术语“堆栈对象”不仅仅是在参数传递方面毫无意义。更一般地说,根本没有任何方法可以告诉编译器在堆栈上分配对象。虽然局部变量通常将分配在堆栈上,但对此没有任何保证。我想这就是您选择转入汇编语言的原因。然后,您可以显式地向堆栈
push
和pop
值(由CPU 管理)。I must admit that even with the additional information you provided, I don't fully understand your question. But let me say something general about the stack and the heap and C++:
How an argument gets passed to the function is an implementation detail of a particular C++ compiler, ie. this can vary from one C++ compiler to the next. The method by which arguments are passed into functions is called a calling convention. Some compilers use neither the stack nor the heap for argument passing; instead, they use CPU registers if possible. (Watcom's C++ compiler is/was a prominent example of a compiler that favours registers to pass arguments to a function.)
This means that any C++ compiler may create binaries that are not binary-compatible to another C++ compiler. (The C++ language standard does not prescribe a binary standard for compiled output, therefore different compilers may produce binary-incompatible output; but any C++ compiler is guaranteed to be binary-compatible at least to itself.) Thus, if you want to use a library, you have three options:
choose a binary that matches your particular C++ compiler and linker;
compile the library sources yourself, using your compiler; or
choose a library binary that adheres to a certain binary standard (such as the DLL library format or Microsoft's COM standard) which is also supported by your C++ compiler and linker.
In conclusion, your question about stack object vs. heap object does not make sense. There is no such thing as a "stack object" in C++. You have no explicit control how an argument is passed to a function, because that is something that the C++ compiler will decide itself how to do -- and while there seem to exist keywords and special syntax to control this behaviour (namely references, pointers, as well as the
auto
andregister
keywords), they generally won't give you any guarantee that a parameter will be passed in a specific way. If you know one particular compiler well, then you might be able to deduce how parameter passing works with this compiler... but generally, you cannot — and should not have to — know about this mechanism.P.S.: I forgot to mention that the term "stack object" is not just meaningless in terms of parameter passing. Even more generally, there simply isn't any way to tell the compiler to allocate an object on the stack. While local variables usually will be allocated on the stack, there is no guarantee whatsoever for this. I suppose that is why you chose to escape into assembly language. You could then explicitly
push
andpop
values to/from the stack (as managed by the CPU).