我想实现通用记录器,它可以帮助我查看方法的调用堆栈。
我知道 System.Diagnostic 有一些方法,但它们是在 .net 4.0 中引入的,恐怕它不适用于 xamarin 或 .net core 或类似的东西。所以我想要更通用的解决方案。
另一个问题是 async\await,它会带来一些混乱。
我通过在每个方法中传递附加参数来存储一些上下文并帮助我确定调用堆栈,但是这个解决方案有点复杂。
我也可以使用不安全代码读取线程堆栈内存并自己检查调用堆栈,但它不可靠。
还有其他解决方案吗?
我正在使用 Visual Studio 调试大型多线程 C++ 应用程序。我试图找出哪个线程运行了我感兴趣的函数。
我有 40 多个线程,其中一些具有非常长的调用堆栈。因此,手动检查单个调用堆栈以查看它们是否包含我的函数真的很乏味。
我想知道 Visual Studio 是否支持搜索调用堆栈,就像它支持搜索源文件一样。你能告诉我如何在 VS 中搜索调用堆栈吗?
我正在 Visual Studio 中调试程序,我想知道为什么我的程序在特定单元(源代码文件)中的函数旁边传递。
我认为调用堆栈会显示这一点,但事实并非如此。此外,可显示条目的列表甚至没有提到文件名:
=> 没有“显示文件名”,尽管“显示行号”的存在意味着文件名应该是已知的。
我正在使用适用于 Windows 桌面的 Visual Studio Professional 2017。
这是一个配置问题,这是否在我的 Visual Studio 安装中不存在(如果是,哪个版本具有此功能)或者在 Visual Studio 中根本没有预见到这一点?
为了便于理解,我的调用堆栈如下所示:
<product>.dll!<first_class>::<first_class>(double dFy, double dFx) Line 102 C++
<product>.dll!<subfunction>(double dFv, double dFh) Line 1450 C++
<product>.dll!<subsubfunction>(double dFv, double dFh, int number) Line 1672 C++
...
Run Code Online (Sandbox Code Playgroud)
虽然我想看到类似的东西:
<product>.dll!<first_class>::<first_class>(double dFy, double dFx) File <file1.c> Line 102 C++
<product>.dll!<subfunction>(double dFv, double dFh) File <file2.c> Line 1450 C++
<product>.dll!<subsubfunction>(double dFv, double dFh, int number) File <file2.c> Line …Run Code Online (Sandbox Code Playgroud) 例如,我发现了一些基于 promise 的 api 库,我需要在某个时间间隔内使用该库发出 api 请求,无限次(如通常的后端循环)。这个 api 请求 - 实际上是承诺链。
所以,如果我写这样的函数:
function r(){
return api
.call(api.anotherCall)
.then(api.anotherCall)
.then(api.anotherCall)
...
.then(r)
}
Run Code Online (Sandbox Code Playgroud)
会导致堆栈溢出吗?
我想出的解决方案是使用 setTimeout 进行r递归调用。
function r(){
return api
.call(api.anotherCall)
.then(api.anotherCall)
.then(api.anotherCall)
.then(()=>{setTimeout(r, 0)})
}
Run Code Online (Sandbox Code Playgroud)
所以 setTimeoutr只会在调用栈为空时才会调用。
这是好的解决方案,还是有一些递归调用承诺的标准方法?
在 5.2 之前的内核版本中,我使用save_stack_trace_tsk来检索调用堆栈。
但是这个方法在Linux kernel 5.2+中不再可用,我应该用什么?
我把一个很简单的C程序转成汇编文件(这里是RISC-V ISA),在堆栈指针上做了一些我不明白的操作。
C程序:
int main()
{
int a = 10;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
相关的汇编代码:
.file "alternating_branches_2.c"
.option nopic
.text
.align 1
.globl main
.type main, @function
main:
addi sp,sp,-32
sd s0,24(sp)
addi s0,sp,32
li a5,10
sw a5,-20(s0)
li a5,0
mv a0,a5
ld s0,24(sp)
addi sp,sp,32
jr ra
.size main, .-main
.ident "GCC: (GNU) 8.3.0"
Run Code Online (Sandbox Code Playgroud)
这是我的理解。
sp 包含堆栈内存的最后一个地址。因此,压入堆栈会降低 sp 的值。s0 是帧指针,指向 sp 的前一个值。
在第一行中,从堆栈指针开始减少 32 的偏移量。这是要创建堆栈帧吗?通常,在堆栈中,推送操作会减少堆栈指针。但是,既然已经创建了一个栈帧,现在sp指向栈的下层内存,push会增加sp的值吗?
-------------| <--sp
-------------|
-------------|
-------------|
-------------|
-------------|
-------------|
Run Code Online (Sandbox Code Playgroud)
创建堆栈帧后:
-------------| <--s0
-------------|
-------------|
-------------|
-------------| …Run Code Online (Sandbox Code Playgroud) 这似乎是一个愚蠢的问题。我尝试了不同的资源来了解如何从调用堆栈中弹出 void 方法。我无法弄清楚,寻求帮助。提前致谢。
一个简单的例子——
public static void main(String args[]){
int sum = sum(2,3);
System.out.println(sum);
}
public static int sum(int first, int second){
return first + second;
}
Run Code Online (Sandbox Code Playgroud)
假设我想将堆栈初始化为S字节大小。
我想选择堆栈的基本位置,B以便随着堆栈从 向下增长B,我最终不会覆盖引导加载程序或 BIOS 使用的任何代码或其他内存。
由于我自己编写引导加载程序(并且初始 MBR 扇区被加载到线性地址0x7c00),防止与引导加载程序发生冲突似乎是一个仔细规划的问题。
我如何知道 BIOS 代码所在的位置,以及我的堆栈是否可能覆盖 BIOS 正在使用的任何内存?
另外,是否可以保证初始ss:sp值指向哪里,以及在不设置新值的情况下可以安全使用多少堆栈空间?
我正在尝试了解以下 python 递归函数的调用堆栈。该函数给出给定集合的所有组合。
def subsets(A):
if not A:
yield []
else:
for s in subsets(A[1:]):
yield s
yield [A[0]] + s
l1=[1,2,3]
print(list(subsets(l1)))
Run Code Online (Sandbox Code Playgroud)
该程序正在根据需要生成输出:
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
Run Code Online (Sandbox Code Playgroud)
但是我无法可视化调用堆栈。它怎么能打印[1,2,3]?我的理解如下
call stack 1 : values are : for s in [2,3], a[0] = 1, a = [1,2,3]
call stack 2 : values are : for s in [3], a[0] = 2, a = [2,3]
call stack 3 : values are …Run Code Online (Sandbox Code Playgroud)