2014-10-21 6 views
1

C에서 프로그램을 실행 중이고 세그먼트 결함이 있습니다. 오류 obout 비트 MRE를 알고 Valgrind의를 실행 한 후 내가 얻을 : 당신이 볼 수 있듯이 나는이 오류를 찾을 수 있도록pthread를 만들 때 세그멘테이션 오류가 발생하는 이유는 무엇입니까?

==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== 

이 오류는 함수 복제에서 시작하지만 난 아무 생각이 왜 키우면이 없다 사고.

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는 597 행의 msp.c 파일에있는 NULL 포인터에 액세스하려고 시도하고 있다고 가정하고, 거기에서 시작하여 어떤 변수가 NULL인지 알아 내고 역방향으로 중첩합니다. 관련이 없을지라도, 쓰래드 생성은 커다란 경쟁 조건을 가지고 있습니다. 스레드에'& newsock'을 전달하기 때문에, 쓰레드가 그것을 사용하기 전에 변수를 새로운 소켓에 재 할당 할 수 있습니다. – nos

+0

이 줄 : while (1) {해야합니다 for (cant_conexiones = 0; cant_conexiones user3629249

답변

0

conexiones 배열 끝에 메모리를 쓰고있는 것이 하나의 이유 일 수 있습니다. 즉, conexiones에는 BACKLOG 항목 만 들어갈 수 있지만, while (1) 루프는 pthread_create의 첫 번째 인수가 배열 끝에 도달 할 때까지 전달하는 포인터가이 될 때까지 무기한 증가합니다. pthread_create가 쓰기를 시도하면 정의되지 않은 동작 (및 충돌)이 발생합니다.

또 다른 이유는 msp.c의 597 줄에있는 코드 (agregar_nuevo_segmento_al_proceso 함수 안에 있음)가 (4 바이트 오프셋을 사용하여) NULL 포인터를 역 참조하려고하기 때문입니다. 그 코드는 게시되지 않았으므로, 나는 그 이유를 말할 수는 없지만 스택 트레이스의 최상위가 알려주는 것입니다.

관련 문제