segmentation fault의 발생지점을 찾고있습니다.

조회수 2164회

이름과 번호가 부여된 구조체를 각각 배열, Linked-리스트로 만들고 keyword로 검색한 뒤 이름을 검색했으면 번호가, 또는 그 반대결과를 출력하는 것을 목표로 작성했습니다. linux 기반으로 작성하는것이 처음이라 코드 외적인데서 신경을 너무 많이 쓴거같네요.

컴파일 에러는 거의 잡혔는데 제목 그대로 덤프만 발생시키면서 정지되었습니다. 디버깅 툴 사용에 익숙지 않아서 에러메시지도 정확한 의미를 받아들이기가 힘드네요

Program received signal SIGSEGV, Segmentation fault. 0x00010654 in add_node()

이런식으로 나오면 main.c에서 add_node()가 실행되면서 문제가 생긴건가요 아니면 add_node() 함수 자체의 구현에 오류가 있는건가요?

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

typedef struct _Student{
    char name[10];
    char number[10];
} Student;

typedef struct node{
    Student* Std;
    struct node* next;
}NODE;

typedef struct{
    int count;
    NODE* front;
    NODE* rear;
    NODE* pos;
}LLIST;

LLIST* create_list(){
    LLIST* list;
    list = (LLIST*)malloc(sizeof(LLIST));
    if(list){
        list->front = NULL;
        list->rear = NULL;
        list->count = 0;
    }
    return list;
}

void add_node(LLIST* list,  Student* Std_info) {
    NODE* new_node=(NODE*)malloc(sizeof(NODE));

    new_node -> Std = Std_info;
    new_node -> next = NULL;
    if(list -> count == 0){
        list->front = new_node;
        list->rear = new_node;
        (list->count)++;
        return;
    }
    int index = 0;
    list->pos = list->front;
    while(index != (list->count)){
        list->pos = list->pos->next;
        index++;
    }
    //탈출할 시점이면 index 값이 list->count와 같음

    list->pos->next = new_node;
    list->rear = new_node;
    (list->count)++;
    return; //void형을 반환할때는 return값이 없어도 오류가 나지 않음.
}

void del_node(LLIST* list){
    if(list->count == 1){
        free(list->front);
        list->front = NULL;
        list->rear = NULL;
        list->count = 0;
        return;
    }
    int index = 0;
    list->pos = list->front;
    NODE* bckup = NULL;
    while(index != list->count){
        bckup = list->pos;
        list->pos = list->pos->next;
        index++;
    }
    //탈출할 시점에 index값=list->count 값
    list->rear = bckup;
    bckup->next = NULL;
    free(list->pos);
    list->pos=NULL;
    (list->count)--;
    return;
}
char* finderLLIST(LLIST* list, char* keyword){
    if(list->count==0){
        keyword = "빈 리스트";   
        return keyword;
    }   
    int index = 0; 
    list->pos = list->front; //앞부터 시작

    //&&연산자는 앞에서 결과값이 확실해지면 뒤쪽의 항은 계산하지 않는다.
    while(index < list->count && strcmp(list->pos->Std->name,keyword) != 0 && strcmp(list->pos->Std->number,keyword) != 0){ 
        list->pos = list->pos->next;
        index++;
    }

    if(index >= list->count){
        keyword = "일치없음";
    }else if(strcmp(list->pos->Std->name,keyword) == 0){
        keyword = list->pos->Std->number;
    }else if(strcmp(list->pos->Std->number,keyword) == 0){
        keyword = list->pos->Std->name;
    }

    return keyword;
 }


char* finderARR(Student* Std, char* keyword){
    int index;

    for(index=0; index<=9; index++){
        if(strcmp(Std->name,keyword) == 0){
            keyword = (Std+index)->number;
            return keyword;
        }else if(strcmp((Std+index)->number,keyword) == 0){
            keyword = (Std+index)->name;
            return keyword;
        }
    }
    keyword = "일치없음";
    return keyword;
}
int main(void){
    Student Std[10]={
    {.name   = "김김김",.number   = "1234123"},
    {.name   = "님님님",.number   = "2222222"},
    {.name   = "딤딤딤",.number   = "3333333"},
    {.name   = "림림림",.number   = "4444444"},
    {.name   = "밈밈밈",.number   = "5555555"},
    {.name   = "빔빔빔",.number   = "6666666"},
    {.name   = "심심심",.number   = "7777777"},
    {.name   = "임임임",.number   = "8888888"},
    {.name   = "짐짐짐",.number   = "9999999"},
    {.name   = "침침침",.number   = "0000000"}
    };
    int i;

    Student Std_list[10] = {
    {.name   = "김김김",.number   = "1234123"},
    {.name   = "님님님",.number   = "2222222"},
    {.name   = "딤딤딤",.number   = "3333333"},
    {.name   = "림림림",.number   = "4444444"},
    {.name   = "밈밈밈",.number   = "5555555"},
    {.name   = "빔빔빔",.number   = "6666666"},
    {.name   = "심심심",.number   = "7777777"},
    {.name   = "임임임",.number   = "8888888"},
    {.name   = "짐짐짐",.number   = "9999999"},
    {.name   = "침침침",.number   = "0000000"}
    };
    LLIST* list_Std = create_list();
    for(i=0; i<10; i++){
        add_node(list_Std, &Std_list[i]);
    }

    //여기까지는 배열과 연결리스트의 선언과 메모리 할당 및 초기화.
    char keyword[10];

    printf("배열에서 검색: ");
    scanf("%s", keyword);
    //printf("\n버퍼 확인 ㅁㅁ%sㅁㅁ", keyword);
    printf("-->%s \n", finderARR(Std, keyword));


    printf("연결리스트에서 검색: ");
    scanf("%s", keyword);
    //printf("\n버퍼 확인 ㅁㅁ%sㅁㅁ", keyword);
    printf("-->%s", finderLLIST(list_Std, keyword));



    //여기부터는 배열과 연결리스트의 메모리 할당 해제
    for(i=0; i<10; i++){
        del_node(list_Std);
    } 

    free(list_Std);

    return 0;
}
  • 세그먼테이션 오류인데 메모리 오류입니다. 보통 메모리를 할당 안하고 접근하거나 할 때 발생합니다. 가장빠르게 찾는 방법은 gdb 사용법을 익히는겁니다. 정영훈 2020.4.10 01:14
  • 조언 감사합니다. 주석처리해가면서 발생 위치를 찾아내긴 했지만 앞으로는 gdb를 자주 써보는 수 밖에 없는것 같네요. 전성운 2020.4.10 01:43
  • 맞습니다. 컴파일 오류, 런타임 오류는 스스로 해결해야 실력이 늡니다. 이런곳에서 답변을 얻으면 그건 답변자가 한 것이나 다름이 없으니까요. 정영훈 2020.4.10 02:25

1 답변

  • https://code.visualstudio.com/docs/cpp/config-linux#_debug-helloworldcpp

    vs code 설치하고, 위 링크에서 따라해 가면서 빌드, 디버그 설정하면, 그래도 조금 편하게 vs code 안에서 디버깅 해 볼 수 있는 것 같습니다. 한번 따라서 해보세요.

    아래 캡쳐는 우분투에서 설정 따라해서 디버그모드로 돌려서, 예외 발생한 상황입니다. list->pos 값이 NULL 이네요.

    이미지

    • 코드의 디버그가 급할때는 윈도우에서, gdb연습할 시간이 넉넉할때는 리눅스에서 해봐야겠습니다. 특정 값에서의 작동을 설정하다가 index훑는 변수가 한칸씩 밀렸었네요! 전성운 2020.4.10 02:33
    • @전성운 : 윈도우에서 vs 쓰는 게 편하긴 하죠. 근데, vs code 로 디버그 세팅하는 거 해보니까 그렇게 어렵지 않네요. 상당히 많은 거 자동으로 잡아주고요. 기본적인 디버그기능들 쾌적하게 돌아가고요. nowp 2020.4.10 13:16

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)