尽管故障处理程序正常(有时),ARM Cortex M4 会在递归时静默重置

发布于 2025-01-16 11:25:14 字数 7794 浏览 1 评论 0原文

我最近进行了一次在裸机 ARM Cortex M4 平台上实施和测试故障处理程序的练习。实现处理程序后,我还编写了一个非常残酷的应用程序来触发各种错误并查看处理程序如何响应。

顺便说一句,该芯片是Nordic nRF52832。

我写的一个测试是下面的函数(对它的调用被简化了,你实际上需要通过主 UART 发送一个命令来让它杀死自己):

static volatile uint32_t dummy = 1;

uint32_t evil_recursive(uint32_t i)
{
  printf("N:%d MSP: 0x%08x", i, (uint32_t *)__get_MSP());
  return evil_recursive( i + dummy);
}

main()
{
  uint32_t i = evil_recursive(1);
}

这非常难以行为不当,我们需要使用编译器标志

CFLAGS += -fno-optimize-sibling-calls

让它定义新的堆栈帧。编译器似乎将函数展开为 9 个调用的循环(您可以看到每 9 个打印语句 MSP 减少 32)。但是,两分钟后,由于总线故障,它确实出现了故障。到目前为止一切正常。

由于这里的 printf() 将使用一个缓慢的、bitbash 的、阻塞的 UART,为了加快速度,我删除了它。 (这只是为了调试)。令我惊讶的是,调用邪恶函数现在会导致处理器立即重置,并且不会触发任何故障处理程序。

有谁知道为什么会这样吗?我希望这会消耗内存并导致某种处理程序启动。

更多信息:我想知道 print 语句的简单存在是否会改变编译方式或行为。所以我尝试了这个,它运行得更快,但包含基本相同的调用:

uint32_t evil_recursive(uint32_t i)

    {
      static char c = 'A';
      debug_uart_putc(c);
      c++;
      if (c > 'Z') c = 'A';
      return evil_recursive( i + dummy);
    }

这也会重置而不触发任何处理程序。

后来:这就是两个 fn 的编译方式。

第一个确实触发处理程序:

00026678 <evil_recursive>:
   26678:   b5f0        push    {r4, r5, r6, r7, lr}
   2667a:   4e4c        ldr r6, [pc, #304]  ; (267ac <evil_recursive+0x134>)
   2667c:   b083        sub sp, #12
   2667e:   4604        mov r4, r0
   26680:   212f        movs    r1, #47 ; 0x2f
   26682:   4630        mov r0, r6
   26684:   f004 fb8f   bl  2ada6 <strrchr>
   26688:   f3ef 8308   mrs r3, MSP
   2668c:   4f48        ldr r7, [pc, #288]  ; (267b0 <evil_recursive+0x138>)
   2668e:   4d49        ldr r5, [pc, #292]  ; (267b4 <evil_recursive+0x13c>)
   26690:   9301        str r3, [sp, #4]
   26692:   1c41        adds    r1, r0, #1
   26694:   463b        mov r3, r7
   26696:   9400        str r4, [sp, #0]
   26698:   223c        movs    r2, #60 ; 0x3c
   2669a:   2000        movs    r0, #0
   2669c:   f004 fa14   bl  2aac8 <project_log>
   266a0:   682b        ldr r3, [r5, #0]
   266a2:   212f        movs    r1, #47 ; 0x2f
   266a4:   4630        mov r0, r6
   266a6:   441c        add r4, r3
   266a8:   f004 fb7d   bl  2ada6 <strrchr>
   266ac:   f3ef 8308   mrs r3, MSP
   266b0:   223c        movs    r2, #60 ; 0x3c
   266b2:   9301        str r3, [sp, #4]
   266b4:   1c41        adds    r1, r0, #1
   266b6:   9400        str r4, [sp, #0]
   266b8:   463b        mov r3, r7
   266ba:   2000        movs    r0, #0
   266bc:   f004 fa04   bl  2aac8 <project_log>
   266c0:   682b        ldr r3, [r5, #0]
   266c2:   212f        movs    r1, #47 ; 0x2f
   266c4:   4630        mov r0, r6
   266c6:   441c        add r4, r3
   266c8:   f004 fb6d   bl  2ada6 <strrchr>
   266cc:   f3ef 8308   mrs r3, MSP
   266d0:   223c        movs    r2, #60 ; 0x3c
   266d2:   9301        str r3, [sp, #4]
   266d4:   1c41        adds    r1, r0, #1
   266d6:   9400        str r4, [sp, #0]
   266d8:   463b        mov r3, r7
   266da:   2000        movs    r0, #0
   266dc:   f004 f9f4   bl  2aac8 <project_log>
   266e0:   682b        ldr r3, [r5, #0]
   266e2:   212f        movs    r1, #47 ; 0x2f
   266e4:   4630        mov r0, r6
   266e6:   441c        add r4, r3
   266e8:   f004 fb5d   bl  2ada6 <strrchr>
   266ec:   f3ef 8308   mrs r3, MSP
   266f0:   223c        movs    r2, #60 ; 0x3c
   266f2:   9301        str r3, [sp, #4]
   266f4:   1c41        adds    r1, r0, #1
   266f6:   9400        str r4, [sp, #0]
   266f8:   463b        mov r3, r7
   266fa:   2000        movs    r0, #0
   266fc:   f004 f9e4   bl  2aac8 <project_log>
   26700:   682b        ldr r3, [r5, #0]
   26702:   212f        movs    r1, #47 ; 0x2f
   26704:   4630        mov r0, r6
   26706:   441c        add r4, r3
   26708:   f004 fb4d   bl  2ada6 <strrchr>
   2670c:   f3ef 8308   mrs r3, MSP
   26710:   223c        movs    r2, #60 ; 0x3c
   26712:   9301        str r3, [sp, #4]
   26714:   1c41        adds    r1, r0, #1
   26716:   9400        str r4, [sp, #0]
   26718:   463b        mov r3, r7
   2671a:   2000        movs    r0, #0
   2671c:   f004 f9d4   bl  2aac8 <project_log>
   26720:   682b        ldr r3, [r5, #0]
   26722:   212f        movs    r1, #47 ; 0x2f
   26724:   4630        mov r0, r6
   26726:   441c        add r4, r3
   26728:   f004 fb3d   bl  2ada6 <strrchr>
   2672c:   f3ef 8308   mrs r3, MSP
   26730:   223c        movs    r2, #60 ; 0x3c
   26732:   9301        str r3, [sp, #4]
   26734:   1c41        adds    r1, r0, #1
   26736:   9400        str r4, [sp, #0]
   26738:   463b        mov r3, r7
   2673a:   2000        movs    r0, #0
   2673c:   f004 f9c4   bl  2aac8 <project_log>
   26740:   682b        ldr r3, [r5, #0]
   26742:   212f        movs    r1, #47 ; 0x2f
   26744:   4630        mov r0, r6
   26746:   441c        add r4, r3
   26748:   f004 fb2d   bl  2ada6 <strrchr>
   2674c:   f3ef 8308   mrs r3, MSP
   26750:   223c        movs    r2, #60 ; 0x3c
   26752:   9301        str r3, [sp, #4]
   26754:   1c41        adds    r1, r0, #1
   26756:   9400        str r4, [sp, #0]
   26758:   463b        mov r3, r7
   2675a:   2000        movs    r0, #0
   2675c:   f004 f9b4   bl  2aac8 <project_log>
   26760:   682b        ldr r3, [r5, #0]
   26762:   212f        movs    r1, #47 ; 0x2f
   26764:   4630        mov r0, r6
   26766:   441c        add r4, r3
   26768:   f004 fb1d   bl  2ada6 <strrchr>
   2676c:   f3ef 8308   mrs r3, MSP
   26770:   223c        movs    r2, #60 ; 0x3c
   26772:   9301        str r3, [sp, #4]
   26774:   1c41        adds    r1, r0, #1
   26776:   9400        str r4, [sp, #0]
   26778:   463b        mov r3, r7
   2677a:   2000        movs    r0, #0
   2677c:   f004 f9a4   bl  2aac8 <project_log>
   26780:   682b        ldr r3, [r5, #0]
   26782:   4630        mov r0, r6
   26784:   212f        movs    r1, #47 ; 0x2f
   26786:   441c        add r4, r3
   26788:   f004 fb0d   bl  2ada6 <strrchr>
   2678c:   f3ef 8308   mrs r3, MSP
   26790:   223c        movs    r2, #60 ; 0x3c
   26792:   1c41        adds    r1, r0, #1
   26794:   e9cd 4300   strd    r4, r3, [sp]
   26798:   2000        movs    r0, #0
   2679a:   463b        mov r3, r7
   2679c:   f004 f994   bl  2aac8 <project_log>
   267a0:   6828        ldr r0, [r5, #0]
   267a2:   4420        add r0, r4
   267a4:   f7ff ff68   bl  26678 <evil_recursive>
   267a8:   b003        add sp, #12
   267aa:   bdf0        pop {r4, r5, r6, r7, pc}
   267ac:   0002bd28    .word   0x0002bd28
   267b0:   0002bd3c    .word   0x0002bd3c
   267b4:   20003310    .word   0x20003310

这是导致重置的一个(根本没有打印):

00026678 <evil_recursive>:
   26678:   b510        push    {r4, lr}
   2667a:   4a0b        ldr r2, [pc, #44]   ; (266a8 <evil_recursive+0x30>)
   2667c:   6813        ldr r3, [r2, #0]
   2667e:   6811        ldr r1, [r2, #0]
   26680:   440b        add r3, r1
   26682:   6811        ldr r1, [r2, #0]
   26684:   6814        ldr r4, [r2, #0]
   26686:   440b        add r3, r1
   26688:   6811        ldr r1, [r2, #0]
   2668a:   4423        add r3, r4
   2668c:   440b        add r3, r1
   2668e:   6811        ldr r1, [r2, #0]
   26690:   440b        add r3, r1
   26692:   6811        ldr r1, [r2, #0]
   26694:   440b        add r3, r1
   26696:   6811        ldr r1, [r2, #0]
   26698:   6812        ldr r2, [r2, #0]
   2669a:   440b        add r3, r1
   2669c:   4413        add r3, r2
   2669e:   4418        add r0, r3
   266a0:   f7ff ffea   bl  26678 <evil_recursive>
   266a4:   bd10        pop {r4, pc}
   266a6:   bf00        nop
   266a8:   20003310    .word   0x20003310

显然它要小得多。我不太了解ARM汇编程序,我想我要去学习一些......

I recently went through an exercise to implement and test fault handlers on a bare metal ARM Cortex M4 platform. Having implemented handlers, I also wrote a pretty brutal app to trigger various faults and see how the handler responded.

By the way, the chip is a Nordic nRF52832.

One test I wrote was the following function (the call to it is simplified, you actually need to send a command over the main UART to make it kill itself):

static volatile uint32_t dummy = 1;

uint32_t evil_recursive(uint32_t i)
{
  printf("N:%d MSP: 0x%08x", i, (uint32_t *)__get_MSP());
  return evil_recursive( i + dummy);
}

main()
{
  uint32_t i = evil_recursive(1);
}

This was surprisingly difficult to get to misbehave, we needed to use the compiler flag

CFLAGS += -fno-optimize-sibling-calls

to get it to define new stack frames. The compiler seems to unroll the function into loop of 9 calls (you can see MSP decrease by 32 every 9 print statements). But, misbehave it did, after two minutes, with a bus fault. All OK so far.

As printf() here is going to a slow, bitbash, blocking UART, to speed things up, I removed it. (It was just for debug). To my surprise, calling the evil function now causes an immediate reset of the processor, and no fault handler is triggered.

Has anyone any idea why this might be? I would expect this to eat memory and cause some kind of handler to kick in.

MORE INFO : I wondered whether the simple presence of the print statement was changing the way things compile, or the behaviour. So I tried this, which runs much faster but contains basically the same call:

uint32_t evil_recursive(uint32_t i)

    {
      static char c = 'A';
      debug_uart_putc(c);
      c++;
      if (c > 'Z') c = 'A';
      return evil_recursive( i + dummy);
    }

This also resets without triggering any handler.

LATER : this is how the two fn's have been compiled.

First the one that DOES trigger the handler:

00026678 <evil_recursive>:
   26678:   b5f0        push    {r4, r5, r6, r7, lr}
   2667a:   4e4c        ldr r6, [pc, #304]  ; (267ac <evil_recursive+0x134>)
   2667c:   b083        sub sp, #12
   2667e:   4604        mov r4, r0
   26680:   212f        movs    r1, #47 ; 0x2f
   26682:   4630        mov r0, r6
   26684:   f004 fb8f   bl  2ada6 <strrchr>
   26688:   f3ef 8308   mrs r3, MSP
   2668c:   4f48        ldr r7, [pc, #288]  ; (267b0 <evil_recursive+0x138>)
   2668e:   4d49        ldr r5, [pc, #292]  ; (267b4 <evil_recursive+0x13c>)
   26690:   9301        str r3, [sp, #4]
   26692:   1c41        adds    r1, r0, #1
   26694:   463b        mov r3, r7
   26696:   9400        str r4, [sp, #0]
   26698:   223c        movs    r2, #60 ; 0x3c
   2669a:   2000        movs    r0, #0
   2669c:   f004 fa14   bl  2aac8 <project_log>
   266a0:   682b        ldr r3, [r5, #0]
   266a2:   212f        movs    r1, #47 ; 0x2f
   266a4:   4630        mov r0, r6
   266a6:   441c        add r4, r3
   266a8:   f004 fb7d   bl  2ada6 <strrchr>
   266ac:   f3ef 8308   mrs r3, MSP
   266b0:   223c        movs    r2, #60 ; 0x3c
   266b2:   9301        str r3, [sp, #4]
   266b4:   1c41        adds    r1, r0, #1
   266b6:   9400        str r4, [sp, #0]
   266b8:   463b        mov r3, r7
   266ba:   2000        movs    r0, #0
   266bc:   f004 fa04   bl  2aac8 <project_log>
   266c0:   682b        ldr r3, [r5, #0]
   266c2:   212f        movs    r1, #47 ; 0x2f
   266c4:   4630        mov r0, r6
   266c6:   441c        add r4, r3
   266c8:   f004 fb6d   bl  2ada6 <strrchr>
   266cc:   f3ef 8308   mrs r3, MSP
   266d0:   223c        movs    r2, #60 ; 0x3c
   266d2:   9301        str r3, [sp, #4]
   266d4:   1c41        adds    r1, r0, #1
   266d6:   9400        str r4, [sp, #0]
   266d8:   463b        mov r3, r7
   266da:   2000        movs    r0, #0
   266dc:   f004 f9f4   bl  2aac8 <project_log>
   266e0:   682b        ldr r3, [r5, #0]
   266e2:   212f        movs    r1, #47 ; 0x2f
   266e4:   4630        mov r0, r6
   266e6:   441c        add r4, r3
   266e8:   f004 fb5d   bl  2ada6 <strrchr>
   266ec:   f3ef 8308   mrs r3, MSP
   266f0:   223c        movs    r2, #60 ; 0x3c
   266f2:   9301        str r3, [sp, #4]
   266f4:   1c41        adds    r1, r0, #1
   266f6:   9400        str r4, [sp, #0]
   266f8:   463b        mov r3, r7
   266fa:   2000        movs    r0, #0
   266fc:   f004 f9e4   bl  2aac8 <project_log>
   26700:   682b        ldr r3, [r5, #0]
   26702:   212f        movs    r1, #47 ; 0x2f
   26704:   4630        mov r0, r6
   26706:   441c        add r4, r3
   26708:   f004 fb4d   bl  2ada6 <strrchr>
   2670c:   f3ef 8308   mrs r3, MSP
   26710:   223c        movs    r2, #60 ; 0x3c
   26712:   9301        str r3, [sp, #4]
   26714:   1c41        adds    r1, r0, #1
   26716:   9400        str r4, [sp, #0]
   26718:   463b        mov r3, r7
   2671a:   2000        movs    r0, #0
   2671c:   f004 f9d4   bl  2aac8 <project_log>
   26720:   682b        ldr r3, [r5, #0]
   26722:   212f        movs    r1, #47 ; 0x2f
   26724:   4630        mov r0, r6
   26726:   441c        add r4, r3
   26728:   f004 fb3d   bl  2ada6 <strrchr>
   2672c:   f3ef 8308   mrs r3, MSP
   26730:   223c        movs    r2, #60 ; 0x3c
   26732:   9301        str r3, [sp, #4]
   26734:   1c41        adds    r1, r0, #1
   26736:   9400        str r4, [sp, #0]
   26738:   463b        mov r3, r7
   2673a:   2000        movs    r0, #0
   2673c:   f004 f9c4   bl  2aac8 <project_log>
   26740:   682b        ldr r3, [r5, #0]
   26742:   212f        movs    r1, #47 ; 0x2f
   26744:   4630        mov r0, r6
   26746:   441c        add r4, r3
   26748:   f004 fb2d   bl  2ada6 <strrchr>
   2674c:   f3ef 8308   mrs r3, MSP
   26750:   223c        movs    r2, #60 ; 0x3c
   26752:   9301        str r3, [sp, #4]
   26754:   1c41        adds    r1, r0, #1
   26756:   9400        str r4, [sp, #0]
   26758:   463b        mov r3, r7
   2675a:   2000        movs    r0, #0
   2675c:   f004 f9b4   bl  2aac8 <project_log>
   26760:   682b        ldr r3, [r5, #0]
   26762:   212f        movs    r1, #47 ; 0x2f
   26764:   4630        mov r0, r6
   26766:   441c        add r4, r3
   26768:   f004 fb1d   bl  2ada6 <strrchr>
   2676c:   f3ef 8308   mrs r3, MSP
   26770:   223c        movs    r2, #60 ; 0x3c
   26772:   9301        str r3, [sp, #4]
   26774:   1c41        adds    r1, r0, #1
   26776:   9400        str r4, [sp, #0]
   26778:   463b        mov r3, r7
   2677a:   2000        movs    r0, #0
   2677c:   f004 f9a4   bl  2aac8 <project_log>
   26780:   682b        ldr r3, [r5, #0]
   26782:   4630        mov r0, r6
   26784:   212f        movs    r1, #47 ; 0x2f
   26786:   441c        add r4, r3
   26788:   f004 fb0d   bl  2ada6 <strrchr>
   2678c:   f3ef 8308   mrs r3, MSP
   26790:   223c        movs    r2, #60 ; 0x3c
   26792:   1c41        adds    r1, r0, #1
   26794:   e9cd 4300   strd    r4, r3, [sp]
   26798:   2000        movs    r0, #0
   2679a:   463b        mov r3, r7
   2679c:   f004 f994   bl  2aac8 <project_log>
   267a0:   6828        ldr r0, [r5, #0]
   267a2:   4420        add r0, r4
   267a4:   f7ff ff68   bl  26678 <evil_recursive>
   267a8:   b003        add sp, #12
   267aa:   bdf0        pop {r4, r5, r6, r7, pc}
   267ac:   0002bd28    .word   0x0002bd28
   267b0:   0002bd3c    .word   0x0002bd3c
   267b4:   20003310    .word   0x20003310

and here is the one that causes the reset (with no printing at all):

00026678 <evil_recursive>:
   26678:   b510        push    {r4, lr}
   2667a:   4a0b        ldr r2, [pc, #44]   ; (266a8 <evil_recursive+0x30>)
   2667c:   6813        ldr r3, [r2, #0]
   2667e:   6811        ldr r1, [r2, #0]
   26680:   440b        add r3, r1
   26682:   6811        ldr r1, [r2, #0]
   26684:   6814        ldr r4, [r2, #0]
   26686:   440b        add r3, r1
   26688:   6811        ldr r1, [r2, #0]
   2668a:   4423        add r3, r4
   2668c:   440b        add r3, r1
   2668e:   6811        ldr r1, [r2, #0]
   26690:   440b        add r3, r1
   26692:   6811        ldr r1, [r2, #0]
   26694:   440b        add r3, r1
   26696:   6811        ldr r1, [r2, #0]
   26698:   6812        ldr r2, [r2, #0]
   2669a:   440b        add r3, r1
   2669c:   4413        add r3, r2
   2669e:   4418        add r0, r3
   266a0:   f7ff ffea   bl  26678 <evil_recursive>
   266a4:   bd10        pop {r4, pc}
   266a6:   bf00        nop
   266a8:   20003310    .word   0x20003310

obviously it is a lot smaller. I don't know much ARM assembler, I guess I am going to learn some ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

囚你心 2025-01-23 11:25:14

第二个反汇编函数是递归的,每 9 个添加操作使用 8 个字节的堆栈帧。它应该完全按照您的预期溢出堆栈,除了展开循环之外没有编译器有趣的事情。

我会查看堆栈下方内存中的下一个内容。查看数据表中的链接器映射输出和内存映射,看看是否在那里分配了任何内容。尝试创建一个函数,直接从该已知地址下方的一个或多个字节或字读取或写入,然后看看会发生什么。

第一次反汇编有一个更大的框架,因此可能会破坏不同的地址。对未知地址的读取或写入并不总是保证出现总线故障。

我要考虑的另一件事是,北欧的“softdevice”是否惹恼了你?如果您启用了该功能,nRF52 并不是真正的裸机。

Your second disassembly function is recursing with a stack frame of 8 bytes for every 9 add operations. It should overflow the stack exactly as you expect, there is no compiler funnybusiness apart from unrolling the loop.

I would look at what is next in memory below the stack. Look at the linker map output and the memory map in the datasheet and see if anything is assigned there. Try creating a function that just reads or writes from one or more bytes or words below that known address directly and see what happens.

The first disassembly has a bigger frame and so might be clobbering a different address. A read or write to an unknown address doesn't always guarantee a bus fault.

The other thing I would think about is, is the nordic "softdevice" messing with you? nRF52 isn't really quite bare metal if you have that thing enabled.

总以为 2025-01-23 11:25:14

因此,似乎真正的堆栈错误导致了锁定情况,可能是因为处理程序中的函数调用无法在没有堆栈的情况下工作。如果故障发生在故障处理程序内,就会发生这种情况。您可以像这样测试是否发生这种情况:

uint32_t reset_reason = nrf_power_resetreas_get();
printf("RESET REASON: 0x%08x", reset_reason);
if (reset_reason & POWER_RESETREAS_RESETPIN_Msk ) printf("  - reset pin");
if (reset_reason & POWER_RESETREAS_DOG_Msk ) printf("  - watchdog");
if (reset_reason & POWER_RESETREAS_SREQ_Msk ) printf("  - soft reset");
if (reset_reason & POWER_RESETREAS_LOCKUP_Msk ) printf("  - lockup");
if (reset_reason & POWER_RESETREAS_OFF_Msk ) printf("  - GPIO wakeup");
if (reset_reason & POWER_RESETREAS_LPCOMP_Msk ) printf("  - LPCOMP wakeup");
if (reset_reason & POWER_RESETREAS_DIF_Msk ) printf("  - DEBUG wakeup");
if (reset_reason & POWER_RESETREAS_NFC_Msk ) printf("  - NFC wakeup");

在启动时实施这样的检查似乎是个好主意。
我不太清楚为什么具有较长打印语句的版本首先会导致总线错误,但至少这解释了重置。
为了让这个设备很好地处理堆栈溢出,我们可能必须对 MMU 做一些事情,以便在堆栈处于危险的低水平时但在它实际损坏内存的其他区域之前引发错误。

So it seems that a real stack error was causing a lockup condition, probably because function calls within the handler could not work with no stack. If a fault happens within a fault handler, this is what happens. You can test if this is going on like this:

uint32_t reset_reason = nrf_power_resetreas_get();
printf("RESET REASON: 0x%08x", reset_reason);
if (reset_reason & POWER_RESETREAS_RESETPIN_Msk ) printf("  - reset pin");
if (reset_reason & POWER_RESETREAS_DOG_Msk ) printf("  - watchdog");
if (reset_reason & POWER_RESETREAS_SREQ_Msk ) printf("  - soft reset");
if (reset_reason & POWER_RESETREAS_LOCKUP_Msk ) printf("  - lockup");
if (reset_reason & POWER_RESETREAS_OFF_Msk ) printf("  - GPIO wakeup");
if (reset_reason & POWER_RESETREAS_LPCOMP_Msk ) printf("  - LPCOMP wakeup");
if (reset_reason & POWER_RESETREAS_DIF_Msk ) printf("  - DEBUG wakeup");
if (reset_reason & POWER_RESETREAS_NFC_Msk ) printf("  - NFC wakeup");

and it seems like a good idea to implement such a check on boot.
Quite why the version with the longer print statement causes a bus error first, I don't quite know, but at least this explains the reset.
To have this device handle a stack overflow well, we would probably have to do something with the MMU so that an error is raised when the stack is dangerously low, but before it actually corrupts other areas of memory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文