- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这个问题在这里已经有了答案:
How to use “sigaltstack” in signal handler program?
(2 个回答)
去年关闭。
我有以下代码,它进入无限递归并在耗尽分配给它的堆栈限制时触发段错误。我正在 try catch 此段错误并正常退出。但是,我无法在任何信号编号中捕获此段错误。
(客户正面临此问题,并希望针对此类用例提供解决方案。通过诸如“limit stacksize 128M”之类的方式增加堆栈大小使他的测试通过。但是,他要求正常退出而不是段错误。以下代码只是重现了实际问题,而不是实际算法的作用)。
任何帮助表示赞赏。如果我尝试捕捉信号的方式不正确,也请告诉我。编译:g++ test.cc -std=c++0x
#include <iostream>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
int recurse_and_crash (int val)
{
// Print rough call stack depth at intervals.
if ((val %1000) == 0)
{
std::cout << "\nval: " << val;
}
return val + recurse_and_crash (val+1);
}
void signal_handler(int signal, siginfo_t * si, void * arg)
{
std::cout << "Caught segfault\n";
exit(0);
}
int main(int argc, char ** argv)
{
int signal = 11; // SIGSEGV
if (argc == 2)
{
signal = std::stoi(std::string(argv[1]));
}
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = signal_handler;
sa.sa_flags = SA_SIGINFO;
sigaction(signal, &sa, NULL);
recurse_and_crash (1);
}
最佳答案
这是一个要解决的令人惊讶的复杂问题。在这一点上,我不会给出可以工作的代码,而是专注于您遇到的一些“漂亮”问题 - 或者,当您继续为此编码时 - 会遇到。
首先,你为什么要递归?
原因是虽然信号处理程序是“执行上下文传输”,但默认情况下它们没有自己的堆栈。这意味着如果由于堆栈溢出而收到信号,信号处理程序将尝试为可能传递给它的上下文分配堆栈上的空间 - 这只是再次重新抛出相同的信号。
为了确保信号处理程序在它们自己的单独/预分配的堆栈上运行,请使用 sigaltstack()
和 SA_ONSTACK
标志作为 sigaction()
。
其次,根据堆栈溢出的“严重程度”(您的测试程序可能不会触发,但现实世界的程序可能会触发),作为“溢出影响操作”的内存访问(尝试)可能会以除 SIGSEGV
之外的其他信号结束。
您的示例“非特定地”捕获了所有信号,但这在实践中可能相当不足/相当困惑 - 您向您的应用程序发送 SIGUSR1
或 shell /终端在后台发送 SIGTTOU
绝对不表示堆栈溢出。
这意味着还有另一个问题 - 由于堆栈溢出而进行“堆栈外”内存访问时会出现哪些信号?你怎么知道你得到的特定信号是由于堆栈访问引起的?这个答案比第一眼更复杂:
SIGSEGV
。 SIGBUS
。 SIGSEGV
或 SIGBUS
产生影响(例如,在 x86 上,某些指令引发 #GP
,而其他指令 #PF
的读取/写入地址相同 -内核可能将一个转换为 SIGBUS
另一个转换为 SIGSEGV
) char local_to_blow_stack[1ULL << 40]; memset(&local_to_blow_stack, 0, 1);
)并且恰如其分地发生了其他有效的事情是“无论您的堆栈减去什么”),该访问实际上会正常工作。如果没有编译器为您创建“辅助”代码来识别此类访问,实际上有可能您已经破坏了堆栈,并且在最终到达触发信号的内存区域之前仍然进行了多次成功/非信令内存访问。 _np
暗示“不可移植” - 这不能保证在所有系统上都可用,其他人可能有不同的接口(interface)检索此信息) - 但是...找到被访问的内存位置取决于信号和再次访问指令。通常(但不总是)它在
siginfo
(
si_addr
)字段中。
si_addr
,以及那里的地址是否是例如发出内存访问或尝试访问的内存位置的指令在某种程度上取决于系统和硬件(Linux 的行为可能与 Windows 或 MacOSX 不同,并且在 ARM 上与在 x86 上不同)因此您还需要验证“此
si_addr
中的
siginfo_t
位于发出信号的线程堆栈附近”,但也可能验证导致它的指令实际上是内存访问/
si_addr
可以“追溯到”出错的指令。那(找到错误指令的地址/程序计数器)......需要解码信号处理程序的另一个参数,
ucontext_t
......并且你在硬件/操作系统细节中很深很深[在这里递归无限]。
pthread_getattr_np()
检索当前堆栈边界的处理程序,以将
si_addr
与之进行比较。如果您或其他人的生活取决于正确答案,请记住以上内容。
关于c++ - 有没有办法在进程中捕获堆栈溢出? C++ Linux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62432847/
多个 ChildException catch block 和一个 Exception catch block 之间哪个更好? 更好,我的意思是以良好的实践方式。 举例说明: public stati
我正在尝试将脱机计算机记录在文本文件中,以便以后可以再次运行它们。似乎没有被记录或捕获。 function Get-ComputerNameChange { [CmdletBinding()]
我正在将 Scala 'try/catch' 测试代码转换为使用 'intercept' 有没有我不应该使用“拦截”的场景?使用 'intercept' 而不是 'try/catch' 的唯一好处是简
我对erlang很陌生,我正在尝试使用基本的try/catch语句来工作。我正在使用Webmachine处理一些请求,我真正想做的就是解析一些JSON数据并将其返回。如果JSON数据无效,我只想返回一
我不知道如何捕获删除按键。我发现在 ASCII 代码表中,它位于 127 位,但是 if (Key = #127) then 却无济于事。 然后我检查了 VK_DELETE 的值,它是 47。尝试使用
我很少在失败时对数据库查询使用唯一的错误消息 我经常使用简短的标准消息,例如“数据库错误/失败。请与网站管理员联系”或类似的消息。或自动发送给我 我正在寻找一种在PDO中全局设置一次try {}和ca
我有一个变量CompletableFuture completableFuture 。我希望能够使用任何类型的对象来完成它。例如:completableFuture.complete(new Stri
我认为这是基本的东西,但我不知道该怎么做。为什么我得到 IOException never throw in body of相应的 try 语句 public static void main(Str
我在此代码中遇到 JSON 异常: JSONObject jObject = new JSONObject(JSONString); pontosUsuario.setIdUsuari
我正在尝试打印出用单引号括起来的文本。 /bin/bash -lc '/home/CASPER_REPORTS/scripts/CASPER_gen_report.sh CASPER_1' /bin/
我这里遇到了一点问题。我想弄清楚如何捕获 IllegalArgumentException。对于我的程序,如果用户输入负整数,程序应该捕获 IllegalArgumentException 并询问用户
我无法理解 EJBTransactionRolledbackException。 我有实体: @Entity public class MyEntity { @Id @Generate
对于我给自己提出的以下挑战,如果社区的经验给我任何建议,我将不胜感激 - 即,这里有任何关于最佳方法/方向的指示吗? 要求 允许收集/实时监控从用户 Windows PC 到一组特定 IP 地址(或
我想在我的 ABAP 代码中捕获并处理 SAPSQL_DATA_LOSS。 我试过这个: try. SELECT * FROM (rtab_name) AS rtab
我知道捕获错误不是一个好的做法,但在这种情况下,这样做很重要。我正在尝试运行一个包含游戏一部分的 jar,但它给了我一个 unsatisfiedlink 错误,但这是有趣的部分:我正在使用这段代码:
我有一个表单页面,当我保存它时,它会覆盖数据库。表单页面中有一个文本框,允许用户输入 4000 个字符,但如果用户输入的字符超过此值,则会出现以下错误: ERROR 15:54:05 Abstrac
我想知道在python中绑定(bind)键的最简单方法 例如,默认的 python 控制台窗口出现并等待,然后在 psuedo -> if key "Y" is pressed: print (
下面是别人写的类。 我面临的问题是,当它进入parse method时与 null as the rawString ,它正在扔NumberFormatException 。 所以我想做的是,我应该捕
我有一个简单的脚本,可以捕获所有鼠标单击,除非您单击实际有效的内容。链接、Flash 视频等。我如何调整它,以便无论用户点击什么,在视频加载、新页面加载等之前,它都会发送我构建的简单 GET 请求?
我有一个带有一些选择列表的表单,当选择某些值时,这些列表将显示/隐藏更多输入字段。 问题是大多数用户都是数据输入人员,因此他们在输入数据时大量使用键盘,并且选择列表的 change 事件仅在焦点离开输
我是一名优秀的程序员,十分优秀!