创建 pthread 时为什么会出现分段错误?

4

我正在运行一个C程序,但是出现了分段错误。在运行Valgrind以了解更多关于错误的信息后,我得到了以下结果:

==7905== Process terminating with default action of signal 11 (SIGSEGV)
==7905==  Access not within mapped region at address 0x4
==7905==    at 0x8049A65: agregar_nuevo_segmento_al_proceso (msp.c:597)
==7905==    by 0x804990E: cargar_segmento_en_estructuras (msp.c:536)
==7905==    by 0x80498B4: CrearSegmento (msp.c:345)
==7905==    by 0x8049313: comunicacionConMSP (msp.c:161)
==7905==    by 0x804924B: escuchar_kernel (msp.c:135)
==7905==    by 0x8049592: conexion_nueva (msp.c:242)
==7905==    by 0x404AD4B: start_thread (pthread_create.c:308)
==7905==    by 0x4182D3D: clone (clone.S:130)
==7905==  If you believe this happened as a result of a stack
==7905==  overflow in your program's main thread (unlikely but
==7905==  possible), you can try to increase the size of the
==7905==  main thread stack using the --main-stacksize= flag.
==7905==  The main thread stack size used in this run was 8388608.
==7905== 

如您所见,错误开始于函数“clone”,因此我在该函数中寻找错误,但却不知道为什么会发生这种情况。

int main(int argc, char *argv[]) {
    logger = log_create("Log.txt", "MSP", false, LOG_LEVEL_DEBUG);
    //int resultado = GenerarEStructurasAdministrativas();

    LeerArchivoCfg(argv[1]);
    GenerarEstructurasAdministrativas(cantidad_memoria,cantidad_swap);

    pthread_t th1;
    pthread_t conexiones[BACKLOG];
    int cant_conexiones = 0;
    memoria = malloc(cantidad_memoria);

    //Creo hilo para escuchar la consola de la msp
    pthread_create(&th1, NULL, (void *) consola, NULL );
    log_error(logger, "Se ha creado el hilo para atender la consola de la MSP");

    int yes = 1;
    int sock = 0;
    int newsock = 0;
    struct sockaddr_in my_addr;
    struct sockaddr_in their_addr;
    socklen_t sin_size;

    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(puerto);
    my_addr.sin_addr.s_addr = INADDR_ANY;
    memset(&(my_addr.sin_zero), 0, 8);

    //creo el socket
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        log_error(logger, "Error al abrir el socket");
        close(sock);
        exit(1);
    }
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        log_error(logger, "Error en setsockopt.");
        close(sock);
        exit(1);

    }
    if (bind(sock, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))
            == -1) {
        log_error(logger, "Error en funcion bind");
        close(sock);
        exit(1);
    }

    if (listen(sock, BACKLOG) == -1) {
        log_error(logger, "Error en funcion listen");
        close(sock);
        exit(1);
    }

    //acepto la conexión y creo un nuevo hilo que atienda dicha conexion
    while (1) {
        sin_size = sizeof(struct sockaddr_in);
        if ((newsock = accept(sock, (struct sockaddr *) &their_addr, &sin_size))
                == -1) {
            log_error(logger, "Error en accept.");
            continue;
        }
        int p = pthread_create(&conexiones[cant_conexiones], NULL,
                (void *) conexion_nueva, (void *) &newsock);
        cant_conexiones++;
        log_info(logger,p);
    }
    pthread_join(th1, NULL );

    log_destroy(logger);
    free(memoria);
    close(sock);
    return 0;
}

1
从堆栈跟踪的顶部开始,而不是底部。Valgrind说您(可能)正在尝试在msp.c文件的第597行访问空指针,请从那里开始,找出哪个变量为空,然后向后嵌套。虽然可能与此无关,但您的线程创建存在很大的竞争条件,因为您将&newsock传递给线程,该变量在线程开始使用之前可能会被重新分配到新的套接字。 - nos
这行代码:while (1) { 应该改为:for( cant_conexiones=0; cant_conexiones<BACKLOG; cant_conexiones++) {,并且从循环体中删除 cant_conexiones++ 这一行。否则线程的创建将没有停止。 - user3629249
1个回答

1
一种可能是您正在写入超出conexiones数组末尾的内存。也就是说,conexiones只有BACKLOG个空间,但是您的while(1)循环继续无限增加cant_conexiones,直到您传递给pthread_create函数的第一个参数指针超出数组末尾,然后当pthread_create尝试写入它时,会发生未定义的行为(和崩溃)。
另一个原因是msp.c中第597行的代码(位于agregar_nuevo_segmento_al_proceso函数内部)正在尝试解引用一个NULL指针(带有4字节偏移量)。由于该代码未发布,我无法确定原因,但这就是堆栈跟踪顶部告诉您的内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接