0

通常は正常に機能しますが、高負荷でセグメンテーション違反が発生して終了する選択ループをデバッグしています。FD_ISSET()プログラムが、選択セットに追加されていない(正しい)記述子を呼び出すことがあることがわかりました。次のスニペットのように:

#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void die(const char* msg)
{
    fprintf(stderr, "fatal %s", msg);
    exit(1);
}

int main(void)
{
    FILE* file = fopen("/tmp/test", "r");
    if (file == NULL)
        die("fopen");

    int file_fd = fileno(file);
    fd_set read_fds;
    int max_fd = 0;

    FD_ZERO(&read_fds);
    // Only stdin is added to read_fds.
    FD_SET(0, &read_fds);

    if (select(max_fd + 1, &read_fds, NULL, NULL, NULL) < 0)
        die("select");
    if (FD_ISSET(0, &read_fds))
        printf("Can read from 0");
    // !!! Here FD_ISSET is called with a valid descriptor that was 
    // not added to read_fds.
    if (FD_ISSET(file_fd, &read_fds))
        printf("Can read from file_fd");
    return 0;
}

でマークされたチェックが!!!trueを返さないことは明らかですが、それがSEGFAULTの原因である可能性はありますか?このスニペットをvalgrindで実行すると、エラーは報告されませんが、valgrindで負荷テストを実行すると、次のようなエラーが発生することがあります。

==25513== Syscall param select(writefds) points to uninitialised byte(s)
==25513==    at 0x435DD2D: ___newselect_nocancel (syscall-template.S:82)
4

1 に答える 1

2

FD_ISSET()は、ファイル記述子がセットの一部であるかどうかをテストしますread_fds。これは、FD_ISSETがセグメンテーション違反を引き起こしてはならないことを意味します。

FD_ISSETを呼び出す前に、errno値が設定されているかどうかを確認してください。がセグメンテーション違反を引き起こしているselectはずです。

また、file_fd値が。より大きくないことを確認してくださいFD_MAX

于 2012-12-04T15:27:29.167 に答える