3

クラスのメンバー関数で割り込み処理をしようとしています。

コードは

signal(SIGABRT, socketServer.signalHandler);

の定義signalHandler

public:
void SocketServer::signalHandler(int sig)
{
  logger.info("Receive SIG"+to_string(sig)+" Stopping server now...");
  stop();
}

コードをコンパイルすると、次のエラーが表示されました

main.cpp:32:32: error: reference to non-static member function must be called
  signal(SIGABRT, socketServer.signalHandler);

SIGABRTこの関数を使用してキャプチャしsignalHandler、インスタンスをクリーンアップして停止しようとしていsocketServerます。グローバル変数とグローバル関数を使用して仕事をすることができると思いますが、メンバー関数でこれを行うことについて何か考えはありますか?

4

1 に答える 1

3

No, you can not do this.

The reason is that all member functions have an "implied/hidden" this pointer argument. If we "flattened" out your handler definition to produce the C equivalent, it would look like:

void SocketServer::signalHandler(SocketServer *this,int sig);

The signal function [in C] knows nothing of this [pun intended]. If it compiled, the handler would be called with sig going into the this argument and not the sig argument.

So, you really must do:

SocketServer my_global_server;

void
my_handler(int sig)
{

    my_global_server.signalHandler(sig);
}

int
main(void)
{

    signal(SIGABRT,my_handler);

    return 0;
}

Actually, the above is quite dangerous because my_global_server may be in an indeterminate state when the signal handler is called, causing UB. Also, when in a signal handler, there are a limited number of things you are permitted to do. For example, no heap manipulations are permitted.

Here is a better way to implement this:

volatile int signal_flag;

SocketServer my_global_server;

void
my_handler(int sig)
{

    signal_flag = sig;
}

int
main(void)
{

    signal(SIGABRT,my_handler);

    while (! signal_flag) {
        ...
    }

    my_global_server.signalHandler(signal_flag);

    return 0;
}
于 2015-12-15T21:51:34.210 に答える