7

わかりました、これは本当に私を驚かせています。入力を読み取って文字列を返す次の関数があります

unsigned char* readFromIn() {
    unsigned char* text = malloc(1024);
    if (fgets(text, 1024, stdin) != NULL) {          <--This is what's causing segmentation fault
        int textLen = strlen(text);
        if (textLen > 0 && text[textLen - 1] == '\n')
            text[textLen - 1] = '\0';     // getting rid of newline character
        return text;
    }
    else {
        free(text);
        return NULL;
    }
}

問題は、この関数はどこにも呼び出されていないことです。確認のために、関数の名前を 9rawiohawr90awrhiokawrioawr のようなおかしな名前に変更し、関数の先頭に printf ステートメントを配置しました。

呼び出されていない関数がセグメンテーション違反エラーを引き起こす理由が本当にわかりません。

ubuntuでgcc 4.6.3を使用しています。

編集:私はその行を知っています

if (fgets(text, 1024, stdin) != NULL) { 

その条件をコメントアウトするとすぐにセグメンテーションエラーが発生しないため、問題のコードです。

私が入れたprintfデバッグステートメントの出力が表示されないため、関数が呼び出されていないことを知っています。

Edit2: タイプを unsigned char から char に変更しようとしました。まだセグメンテーション エラーです。gdb 出力を取得しようとします。

Edit3: gdb backtrace は以下を生成しました

#0 0xb7fa5ac2 in _IO_2_1_stdin_ () from /lib/i386-linux-gnu/libc.so.6
#1 0xb7faf2fb in libwebsocket_create_context (info=0xbffff280) at libwebsockets.c:2125
#2 0x0804a5bb in main()

フレーム 0,1,2 を実行しても、特に興味深いものは何も出力されません。

Edit4: コメントのすべての提案を試しましたが、役に立たず、同じセグメンテーション エラーが発生します。

そこで、Ubuntu の新しいコピーを仮想 OS にインストールし、コードを再コンパイルしました。それでも同じ問題が発生します。 問題は、私のコードまたはライブラリ自体で行われているあいまいさのいずれかにあるようです。問題を示す最小限の例を作成しました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libwebsockets.h>


unsigned char* readFromIn() {
    unsigned char* text = malloc(1024);
    if (fgets(text, 1024, stdin) != NULL) { <--SEGMENTATION FAULT HERE
        int textLen = strlen(text);
        if (textLen > 0 && text[textLen - 1] == '\n')
            text[textLen - 1] = '\0';    
        return text;
    }
    else {
        free(text);
        return NULL;
    }
}

int callback_http(struct libwebsocket_context *context,
                         struct libwebsocket *wsi,
                         enum libwebsocket_callback_reasons reason, void *user,
                         void *in, size_t len)
{
    return 0;
}

static struct libwebsocket_protocols protocols[] = {
    /* first protocol must always be HTTP handler */
    {
        "http-only",   // name
        callback_http, // callback
        0              // per_session_data_size
    }
};

int main(void) {
    printf("Initializing Web Server\n");
        // server url will be http://localhost:8081
    int port = 8081;
    const char *interface = NULL;
    struct libwebsocket_context *context;
    // we're not using ssl
    const char *cert_path = NULL;
    const char *key_path = NULL;
    // no special options
    int opts = 0;


    struct lws_context_creation_info info;

    memset(&info, 0, sizeof info);
    info.port = port;
    info.iface = interface;
    info.protocols = protocols;
    info.extensions = libwebsocket_get_internal_extensions();
    info.ssl_cert_filepath = NULL;
    info.ssl_private_key_filepath = NULL;
    info.gid = -1;
    info.uid = -1;
    info.options = opts;

    context = libwebsocket_create_context(&info);
    if (context == NULL) {
        fprintf(stderr, "libwebsocket init failed\n");
        return 0;
    }

    printf("starting server...\n");

    while (1) {
        libwebsocket_service(context, 50);
    }
    printf("Shutting server down...\n");
    libwebsocket_context_destroy(context);

    return 0;
}

そして、これが私のコードをコンパイルした方法です

gcc -g testbug.c -o test -lwebsockets

使っているライブラリはこちら

http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/tag/?id=v1.23-chrome32-firefox24

関数 readFromIn() をまだ呼び出していないことがわかります。実行可能ファイルを実行しようとするとすぐにセグメンテーション違反が発生します。

gdb を再実行したところ、今度はバックトレースとフレームからもう少し詳しい情報が得られました。

(gdb) run
Starting program: /home/l46kok/Desktop/websocketserver/test 
Initializing Web Server
[1384002761:2270] NOTICE: Initial logging level 7
[1384002761:2270] NOTICE: Library version: 1.3 unknown-build-hash
[1384002761:2271] NOTICE:  Started with daemon pid 0
[1384002761:2271] NOTICE:  static allocation: 4448 + (12 x 1024 fds) = 16736 bytes
[1384002761:2271] NOTICE:  canonical_hostname = ubuntu
[1384002761:2271] NOTICE:  Compiled with OpenSSL support
[1384002761:2271] NOTICE:  Using non-SSL mode
[1384002761:2271] NOTICE:  per-conn mem: 124 + 1360 headers + protocol rx buf
[1384002761:2294] NOTICE:  Listening on port 8081

Program received signal SIGSEGV, Segmentation fault.
0xb7fb1ac0 in _IO_2_1_stdin_ () from /lib/i386-linux-gnu/libc.so.6
(gdb) backtrace
#0  0xb7fb1ac0 in _IO_2_1_stdin_ () from /lib/i386-linux-gnu/libc.so.6
#1  0xb7fcc2c6 in libwebsocket_create_context () from /usr/local/lib/libwebsockets.so.4.0.0
#2  0x080488c4 in main () at testbug.c:483
(gdb) frame 1
#1  0xb7fcc2c6 in libwebsocket_create_context () from /usr/local/lib/libwebsockets.so.4.0.0
(gdb) frame 2
#2  0x080488c4 in main () at testbug.c:483
483         context = libwebsocket_create_context(&info);

そうですね..手元にあるすべての情報を提供したと思います..しかし、何が問題なのか本当にわかりません。プログラムは 483 行目でセグメンテーション違反を引き起こしますが、呼び出されていない問題のある関数をコメントアウトすると、問題はなくなりました。

4

1 に答える 1

10

おそらく、libwebsockets を初期化するときに何かが足りないのでしょう。

実際、デバッグを使用して libwebsockets を再コンパイルすると、次のことが明らかになります。

GNU gdb (GDB) 7.6.1 (Debian 7.6.1-1)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/vili/x...done.
(gdb) r
Starting program: /home/vili/./x
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
Initializing Web Server
[1384020141:5692] NOTICE: Initial logging level 7
[1384020141:5692] NOTICE: Library version: 1.2
[1384020141:5693] NOTICE:  Started with daemon pid 0
[1384020141:5693] NOTICE:  static allocation: 5512 + (16 x 1024 fds) = 21896 bytes
[1384020141:5693] NOTICE:  canonical_hostname = x220
[1384020141:5693] NOTICE:  Compiled with OpenSSL support
[1384020141:5693] NOTICE:  Using non-SSL mode
[1384020141:5693] NOTICE:  per-conn mem: 248 + 1328 headers + protocol rx buf
[1384020141:5713] NOTICE:  Listening on port 8081

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bc2080 in _IO_2_1_stderr_ () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0  0x00007ffff7bc2080 in _IO_2_1_stderr_ () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007ffff7bcd83c in libwebsocket_create_context (info=0x7fffffffe580)
    at libwebsockets.c:2093
#2  0x0000000000400918 in main () at x.c:66
(gdb) up
#1  0x00007ffff7bcd83c in libwebsocket_create_context (info=0x7fffffffe580)
    at libwebsockets.c:2093
2093                    info->protocols[context->count_protocols].callback(context,
(gdb) p context->count_protocols
$1 = 1
(gdb) p info->protocols[1]
$2 = {
  name = 0x7ffff7bc2240 <_IO_2_1_stdin_> "\210 \255", <incomplete sequence \373>, callback = 0x7ffff7bc2080 <_IO_2_1_stderr_>,
  per_session_data_size = 140737349689696, rx_buffer_size = 0,
  owning_server = 0x602010, protocol_index = 1}
(gdb)

libwebsocket_protocolslib が info->protocols を介して取得したエントリの数を知ることができるように、特別なエントリ (NULL) での配列を閉じる必要がある可能性が非常に高いです。

編集: はい、ドキュメントを確認してください: http://jsk.pp.ua/knowledge/libwebsocket.html

サポートされているプロトコルと、それぞれのプロトコル固有のコールバックをリストする構造体の配列。リストは、NULL コールバック ポインターを持つエントリで終了します。

于 2013-11-09T18:12:40.727 に答える