Ошибка сегментации из функции, которая вообще не вызывается

хорошо,это действительно пугает меня. У меня есть следующая функция, которая просто читает ввод и возвращает строку

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] = '';     // getting rid of newline character
        return text;
    }
    else {
        free(text);
        return NULL;
    }
}

дело в том, что эта функция нигде не вызывается и просто для подтверждения я изменил имя функции на что-то сумасшедшее, как 9rawiohawr90awrhiokawrioawr и поставил оператор printf в верхней части функции.

Я действительно не уверен, почему неконтролируемая функция может вызвать ошибку ошибки сегментации.

Я использую gcc 4.6.3 на ubuntu.

Edit: я знаю, что строка

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 на виртуальной ОС и перекомпилировал свой код. все та же проблема возникает. Мне кажется, проблема либо в какой-то неизвестности. происходит в моем коде или в самой библиотеке. Я создал минимальный пример, демонстрирующий проблему:

#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] = '';    
        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 Servern");
        // 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 failedn");
        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, и на этот раз backtrace и кадры говорят мне немного больше информации.

(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, но проблема исчезает, когда я комментирую оскорбительную функцию, которая не вызывается.

1 ответов


Вероятно, вы что-то упускаете при инициализации libwebsockets.

действительно, перекомпиляция libwebsockets с debug показывает, что:

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
(gdb) p info->protocols[1]
 = {
  name = 0x7ffff7bc2240 <_IO_2_1_stdin_> "0 5", <incomplete sequence 3>, 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.

Edit: да, проверьте документы:http://jsk.pp.ua/knowledge/libwebsocket.html

список массивов структур поддерживаемые протоколы и определенный протокол обратного вызова для каждого из них. Список заканчивается запись имеет указатель обратного вызова NULL.