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 回溯产生以下

#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 副本并重新编译了我的代码。仍然会出现同样的问题。 在我看来,问题在于我的代码或库本身的一些晦涩难懂。我创建了一个演示问题的最小示例:

#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_protocols使用特殊条目 (NULL) 关闭数组,以便 lib 知道它通过 info->protocols 获得了多少条目。

编辑:是的,检查文档:http: //jsk.pp.ua/knowledge/libwebsocket.html

列出支持的协议和每个协议特定回调的结构数组。该列表以具有 NULL 回调指针的条目结束。

于 2013-11-09T18:12:40.727 回答