我正在学习Win32编程,WinMain
原型如下:
int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )
Run Code Online (Sandbox Code Playgroud)
我很困惑这个WINAPI
标识符的用途和发现:
#define WINAPI __stdcall
Run Code Online (Sandbox Code Playgroud)
这是做什么的?在返回类型之后,我对此感到困惑.什么是__stdcall
?当返回类型和函数名称之间有什么东西时,它是什么意思?
我试图更深入地了解编程语言的低级操作是如何工作的,尤其是它们如何与OS/CPU交互.我可能已经在Stack Overflow上的每个堆栈/堆相关线程中阅读了每个答案,并且它们都很棒.但还有一件事我还没有完全理解.
在伪代码中考虑这个函数,这往往是有效的Rust代码;-)
fn foo() {
let a = 1;
let b = 2;
let c = 3;
let d = 4;
// line X
doSomething(a, b);
doAnotherThing(c, d);
}
Run Code Online (Sandbox Code Playgroud)
这就是我假设堆栈在X行上的样子:
Stack
a +-------------+
| 1 |
b +-------------+
| 2 |
c +-------------+
| 3 |
d +-------------+
| 4 |
+-------------+
Run Code Online (Sandbox Code Playgroud)
现在,我读到的关于堆栈如何工作的一切都是它严格遵守LIFO规则(后进先出).就像.NET,Java或任何其他编程语言中的堆栈数据类型一样.
但如果是这样,那么在X行之后会发生什么?显然,接下来我们需要的是使用a
和b
,但这意味着操作系统/ CPU(?)必须弹出d
并c
首先回到a
和b
.但是它会在脚下射击,因为它需要c
并且d
在下一行.
所以,我想知道幕后究竟发生了什么?
另一个相关问题.考虑我们传递对其他函数的引用,如下所示:
fn foo() {
let …
Run Code Online (Sandbox Code Playgroud) AMD has an ABI specification that describes the calling convention to use on x86-64. All OSes follow it, except for Windows which has it's own x86-64 calling convention. Why?
Does anyone know the technical, historical, or political reasons for this difference, or is it purely a matter of NIHsyndrome?
I understand that different OSes may have different needs for higher level things, but that doesn't explain why for example the register parameter passing order on Windows is rcx - rdx …
我正在观看Chandler Carruth在CppCon 2019中的演讲:
在该示例中,他举例说明了您对使用std::unique_ptr<int>
over和会产生多少开销而感到惊讶int*
。该段大约在时间点17:25开始。
您可以看一下他的示例代码对(godbolt.org)的编译结果 -可以看到,确实,编译器似乎不愿意传递unique_ptr值-实际上,底线是只是一个地址-在寄存器内,仅在直接内存中。
Carruth先生在27:00左右提出的观点之一是,C ++ ABI要求按值传递参数(某些但不是全部;也许-非基本类型?而不是在寄存器中。
我的问题:
PS-为了不给这个问题留下代码:
普通指针:
void bar(int* ptr) noexcept;
void baz(int* ptr) noexcept;
void foo(int* ptr) noexcept {
if (*ptr > 42) {
bar(ptr);
*ptr = 42;
}
baz(ptr);
}
Run Code Online (Sandbox Code Playgroud)
唯一指针:
using std::unique_ptr;
void bar(int* ptr) noexcept;
void baz(unique_ptr<int> ptr) noexcept;
void foo(unique_ptr<int> ptr) noexcept {
if (*ptr > 42) {
bar(ptr.get());
*ptr = 42;
}
baz(std::move(ptr));
}
Run Code Online (Sandbox Code Playgroud) 我目前正在开发一个Windows的C++库,它将作为DLL发布.我的目标是最大化二进制互操作性; 更确切地说,我的DLL中的函数必须可以从使用多个版本的MSVC++和MinGW编译的代码中使用,而无需重新编译DLL.但是,我对哪种调用约定是最好的cdecl
或者很困惑stdcall
.
有时我会听到诸如"C调用约定是唯一一个保证编译器相同的语句"的陈述,这与诸如" 解释中存在一些变化cdecl
,特别是如何返回值 "之类的陈述形成对比.这似乎并没有阻止某些库开发人员(如libsndfile)在他们分发的DLL中使用C调用约定,而没有任何明显的问题.
另一方面,stdcall
调用约定似乎是明确定义的.据我所知,所有Windows编译器基本上都需要遵循它,因为它是用于Win32和COM的约定.这是基于这样的假设:没有Win32/COM支持的Windows编译器不会非常有用.在论坛上发布的很多代码片段都声明了函数,stdcall
但我似乎无法找到一个明确解释原因的帖子.
那里有太多相互矛盾的信息,我运行的每一次搜索都给出了不同的答案,这些答案并没有真正帮助我在两者之间作出决定.我正在寻找一个清晰,详细,有争议的解释,为什么我应该选择一个而不是另一个(或者为什么两者是等价的).
请注意,这个问题不仅适用于"经典"函数,还适用于虚拟成员函数调用,因为大多数客户端代码将通过"接口",纯虚拟类(以下描述的模式,例如此处和那里)与我的DLL接口.
可能重复:
如何找到调用当前方法的方法?
我在对象中有一个方法,从对象中的许多地方调用.是否有一种快速简便的方法来获取调用此流行方法的方法的名称.
伪代码示例:
public Main()
{
PopularMethod();
}
public ButtonClick(object sender, EventArgs e)
{
PopularMethod();
}
public Button2Click(object sender, EventArgs e)
{
PopularMethod();
}
public void PopularMethod()
{
//Get calling method name
}
Run Code Online (Sandbox Code Playgroud)
在内部,PopularMethod()
我希望看到Main
它是否被调用的价值Main
......我想看看" ButtonClick
"是否PopularMethod()
被调用ButtonClick
我在看,System.Reflection.MethodBase.GetCurrentMethod()
但这不会让我得到调用方法.我看过这个StackTrace
类,但是每次调用该方法时我都不喜欢运行整个堆栈跟踪.
自从我上次编写手臂汇编程序以来已经有一段时间了,我对细节有点生疏.如果我从arm调用C函数,我只需要担心保存r0-r3和lr,对吧?
如果C函数使用任何其他寄存器,它是否负责保存堆栈中的那些并恢复它们?换句话说,编译器会生成代码来为C函数执行此操作.
例如,如果我在汇编程序函数中使用r10,我不必将其值放在堆栈或内存中,并在C调用后弹出/恢复它,是吗?
这是针对arm-eabi-gcc 4.3.0.
我们最近试图将一些Visual Studio项目拆分成库,一切似乎都在一个测试项目中编译和构建,其中一个库项目作为依赖项.但是,尝试运行该应用程序给了我们以下令人讨厌的运行时错误消息:
运行时检查失败#0 - ESP的值未在函数调用中正确保存.这通常是调用使用不同调用约定声明的函数指针的结果.
我们甚至从未为函数指定调用约定(__cdecl等),使所有编译器开关都处于默认状态.我检查过,项目设置与整个库和测试项目的调用约定是一致的.
更新:我们的一个开发人员将"基本运行时检查"项目设置从"两者(/ RTC1,等同于/ RTCsu)"更改为"默认",运行时间消失,使程序运行正常.我完全不相信这一点.这是一个合适的解决方案,还是一个危险的黑客?
x86-64 System V ABI(用于除Windows之外的所有内容)过去常常访问http://x86-64.org/documentation/abi.pdf,但该网站现已脱离互联网.
该文件是否有新的权威主页?