gpt4 book ai didi

c++ 在不使用全局变量的情况下捕获 ctrl+c

转载 作者:太空宇宙 更新时间:2023-11-04 01:16:53 27 4
gpt4 key购买 nike

为了便于解释,我简化了示例。我正在编写一个计数为 100 的应用程序,但在任何给定时间我都允许用户通过输入 ctrl+c 来取消该程序。通过键盘。

由于我对函数指针的了解不足,看似简单的程序很快就变得复杂起来。这就是我正在尝试做的:

  1. ctrl+c 时捕获 SIGINT 信号被按下。
  2. 捕获后,调用关闭第三方资源的成员函数。

要注意的是,与 Michael Haidl 的两个例子不同和 Grijesh Chauhan给予捕获SIGINT , 我不允许存储任何全局变量。理想情况是所有变量和函数调用都与 signal() 相关被封装在我的一个类中。

这是我基于 HaidlGrijesh 代码的修改尝试:

#include <thread>
#include <chrono>
#include <functional>
#include <iostream>
#include <signal.h>

class MyClass {
public:
volatile sig_atomic_t cancel = 0;
void sig_handler(int signal) {
cancel = true;
this->libCancel();
}
void libCancel() { std::cout << "Cancel and cleanup" << std::endl; }
};

int main(int argc, char *argv[]) {

MyClass mc;
//using std::placeholders::_1;
//std::function<void(int)> handler = std::bind(&MyClass::sig_handler, mc, _1);
//signal(SIGINT, handler);
signal(SIGINT, &mc.sig_handler); // **compiler error**

for (int i = 0; !mc.cancel && i < 100; ++i)
{
std::cout << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}

如您所见,我希望代码简单地数到 100 并在一切顺利时退出。但是如果用户调用 ctrl+c那么类应该处理 SIGINT ,调用外部库进行清理,for循环将退出。

主要问题是我似乎无法设置 signal()绑定(bind)到我的 MyClass::sig_handler 实例的声明.我什至尝试将我的成员函数转换为 std::functionsignal() 使用, 被注释掉了,但是编译器对 C++ function<void(int)> 的事实并不满意不等同于 C 语言 void (*)(int) .

欢迎任何批评。我完全不受我所写内容的束缚,而且我显然对如何将函数指针与成员函数一起使用没有很好的基本理解。

最佳答案

不可能使用局部变量在信号处理程序和程序的其余部分之间进行通信。除了引发的信号外,没有任何参数被传递到处理程序中,并且处理程序不返回任何值。

“全局变量”这个词有些含糊。人们有时会根据上下文表达不同的意思。如果您的限制仅适用于全局范围,则只需在某个命名空间内使用 volatile sig_atomic_t。或者,如果您愿意,也可以使用静态成员变量。

如果您的限制适用于静态存储持续时间,那么您可以改用线程局部变量。

如果您的限制适用于所有全局内存,那么使用信号处理程序无法解决您的问题。您只需要某种全局变量。


如果您可以依赖 POSIX 而不是 C++ 标准,则在没有全局变量的情况下处理 SIGINT 的方法是确保它 被处理,并阻塞线程信号等待。如果调用返回 SIGINT,则停止程序,否则对捕获的信号执行您想执行的操作。

当然,这意味着阻塞线程除了等待信号外什么都不做。您需要在其他线程中完成实际工作。

但从技术上讲,可能仍在使用全局内存。使用简单地隐藏在系统库中。


此外,在信号处理程序中使用 std::cout 是不安全的。我知道这只是一个例子,但是“调用外部库进行清理”很可能异步信号也不安全。

这可以通过在 for 循环外而不是在处理程序内调用清理来简单地解决。


The main problem is that I can't seem to setup the signal() declaration to bind to my instance of MyClass::sig_handler.

那是因为signal 需要一个函数指针(void(int) 类型)。函数指针不能指向非静态成员函数。它们只能由成员函数指针指向,signal 不接受。

关于c++ 在不使用全局变量的情况下捕获 ctrl+c,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56140057/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com