当谈到C#中的线程时,我是一个菜鸟,我不确定每个线程是否应该有自己的调用堆栈?基本上,如果我得到"运行时检查失败#0 - ESP的值不正确",那只会崩溃它发生的线程,还是整个程序?
我正在用C++实现一个日志处理程序,它运行良好,但是有一件事我觉得可以使用,这就是记录器得到输出的地方.
我想这不是一个大问题,但我偶然发现了__func__标识符,它基本上会保留当前函数的函数名称.
所以我在我的Log类中有一个静态函数Write,它需要一个日志级别和一个变化列表.所以我会这样称呼它:
Log::Write(LOG_DEBUG, "this is an integer: %d", 10);
Run Code Online (Sandbox Code Playgroud)
它会打印:
2013-01-02 => 10:12:01.366 [DEBUG]: this is an integer: 10
Run Code Online (Sandbox Code Playgroud)
但是我认为在消息中也有调用者可能有用这样的东西:
2013... => 10:12:... (functionName) [DEBUG]: blah
Run Code Online (Sandbox Code Playgroud)
所以我可以做的(当然)是添加__func__作为参数Log::Write,但这意味着任何时候我打电话Log::Write我也需要发送__func__总是相同的,我觉得应该可以做到没有明确地这样说.
所以我想要的是提供的功能:
Log::Write(LOG_DEBUG, __func__, "message");
Run Code Online (Sandbox Code Playgroud)
无需每次都明确输入func.
我不知道这是否真的可行,我得到的最好的选择是有一些方法可以取消引用函数内部的调用者Write,我似乎不太可能只是"推断"这样的参数.但至少值得一提,也许我可以看看有哪些选择.
谢谢.
请向我解释在此代码中“x”是堆栈动态变量还是堆动态变量?如果是堆动态变量,那么为什么它不是堆栈动态变量?谢谢
function foo(){ MyClass x = new MyClass();}
Run Code Online (Sandbox Code Playgroud) 我刚刚发现 push 指令可以有一个立即数 byte 、 word 、 dword 参数,并且每个参数都有不同的操作码。我正在阅读的书中没有示例,所以我不明白汇编程序如何区分这三种类型。例如,如果我编写push 12h汇编器将如何解释它以及堆栈上实际会发生什么?
我想知道在我们得到堆栈溢出异常之前我们可以在c#中执行多少调用
所以我决定写下面的代码
static void Method2(int Calls)
{
if(!Calls.Equals(0))
Method1(--Calls);//if more calls remain call method1 and reduce counter
}
static void Method1(int Calls)
{
if (!Calls.Equals(0))//if more calls remain call method2 and reduce counter
Method2(--Calls);
}
static void Main(string[] args)
{
var Calls= 42994;//number of calls(stack overflow appears for large number)
Method1(Calls);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是编译器如何决定抛出堆栈溢出异常是关于内存限制的?一旦我把42995我得到stackoverflow但这个数字不是恒定所以这是如何工作的?
我知道call并且ret会修改espand that的值push并且pop有许多变体,但是还有其他指令会影响堆栈指针吗?
我是Go的新手,来自Node.JS.
在Node中,如果我运行它:
function run(tick = 0) {
if (tick < 1000000) {
return run(tick + 1);
}
return 0;
}
console.log(run());
Run Code Online (Sandbox Code Playgroud)
程序将崩溃,因为超出了最大调用堆栈大小.
如果我在Go中这样做:
package main
import "fmt"
func run(tick int) (int) {
if (tick < 1000000) {
return run(tick + 1)
}
return 0
}
func main() {
fmt.Println(run(0))
}
Run Code Online (Sandbox Code Playgroud)
这将运行并打印0到stdout.
我的问题是:
最近,我正在尝试在 x86_64 中测试 clang-8 的“影子调用堆栈”功能。但是当我运行“shadowed”程序时,即使它是一个“Hello_World”程序,它也会不断抛出分段错误。我的编译命令是“clang-8 -fsanitize=shadow-call-stack normal.c”。“normal.c”只是一个简单的 hello_world c 程序:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello World!\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
main函数的汇编代码在这里:
0x0000000000401130 <+0>: mov (%rsp),%r10
0x0000000000401134 <+4>: xor %r11,%r11
0x0000000000401137 <+7>: addq $0x8,%gs:(%r11)
0x000000000040113c <+12>: mov %gs:(%r11),%r11
0x0000000000401140 <+16>: mov %r10,%gs:(%r11)
0x0000000000401144 <+20>: push %rbp
0x0000000000401145 <+21>: mov %rsp,%rbp
0x0000000000401148 <+24>: sub $0x20,%rsp
0x000000000040114c <+28>: movl $0x0,-0x4(%rbp)
0x0000000000401153 <+35>: mov %edi,-0x8(%rbp)
0x0000000000401156 <+38>: mov %rsi,-0x10(%rbp)
0x000000000040115a <+42>: movabs $0x402004,%rdi
0x0000000000401164 <+52>: mov $0x0,%al
0x0000000000401166 <+54>: callq 0x401030 …Run Code Online (Sandbox Code Playgroud) 假设我有一个像这样的 nasm 函数:
inc:
mov rax,[rsp + 8]
add [rax],BYTE 1
ret
Run Code Online (Sandbox Code Playgroud)
我这样调用这个函数:
push some_var
call inc
Run Code Online (Sandbox Code Playgroud)
我想通过堆栈将参数传递给函数,因此我压入some_var然后调用我的函数。在函数中,我的项目位于堆栈中的第二个,因此我将其视为:mov rax,[rsp+8]
我的问题是:调用函数后我应该以某种方式从堆栈中弹出我的参数吗?如果是这样,我可以以某种方式从堆栈中删除它,我的意思是弹出它,但不注册?(因为我不再需要这个论点了。)
更新:我发现我可以简单地add rsp,8从堆栈中删除项目。但这是好的做法吗?调用函数后从堆栈中删除参数?
我已经对堆栈的目的进行了哲学思考,经过一些编码后,我发现它的强度是什么.我的胃口唯一的东西是它如何与功能一起使用?我尝试使用通用寄存器添加两个数字做一些简单的功能,但我想这不是它在C中的工作方式,例如..所有参数,局部变量和存储结果在哪里?
你会如何将它重写为汇编程序?(C编译器如何重写它?)
int function(int a, int &b, int *c){
return a*(b++)+(*c);
}
Run Code Online (Sandbox Code Playgroud)
我知道这个例子有点糟透..但这样我就能理解所有的可能性