혹시 이 코드 어떤 부분에서 segmentation falut가 떴는지 알려주실 수 있으실까요?

김태민@Google의 이미지

C언어로 split 함수를 구현해봤습니다.
테스트를 돌렸는데 segmentation fault가 발생했습니다.

    size_t  ft_count_words(const char *s, char c)
    {
        size_t  i;
        size_t  count;
        size_t  ibool;
 
        i = 0;
        count = 0;
        ibool = 1;
        while (s[i])
        {
            while (s[i] == c && s[i])
                i++;
            while (s[i] != c && s[i])
            {
                if (ibool == 1)
                    count++;
                ibool = 0;
                i++;
            }
            ibool = 1;
        }
        return (count);
    }
 
    size_t  ft_splitlen(const char *str, char c)
    {
        size_t  i;
 
        i = 0;
        while (str[i] != c && str[i])
            i++;
        return (i);
    }
 
    char    *ft_splitdup(const char *str, char c)
    {
        char    *word;
        size_t  i;
 
        i = 0;
        if (!(word = (char *)malloc((ft_splitlen(str, c) + 1) * sizeof(char))))
            return (NULL);
        while (str[i] != c && str[i])
        {
            word[i] = str[i];
            i++;
        }
        word[i] = '\0';
        return (word);
    }
 
    char    **ft_splitfree(char **base_split)
    {
        size_t  i;
 
        i = 0;
        while (base_split[i])
        {
            free(base_split[i]);
            i++;
        }
        free(base_split);
        return (NULL);
    }
 
    char    **ft_split(const char *s, char c)
    {
        char    **best_split;
        size_t  i;
        size_t  j;
 
        if (!s || !c)
            return (NULL);
        i = 0;
        j = 0;
        if (!(best_split = (char **)malloc((ft_count_words(s, c) + 1)\
                        * sizeof(char *))))
            return (NULL);
        while (s[i])
        {
            while (s[i] == c && s[i])
                i++;
            while (s[i] != c && s[i])
            {
                if (!(best_split[j] = ft_splitdup(s + i, c)))
                    return (ft_splitfree(best_split));
                i += ft_splitlen(s + i, c);
                j++;
            }
        }
        best_split[j] = NULL;
        return (best_split);
    }
 
    int                 main()
    {
        char **test;
        test = ft_split("lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse", ' ');
    }

vingrind를 사용해서 메모리 누수를 체크해봤더니 아래와 같이 메세지가 출력됐습니다.

==348== Memcheck, a memory error detector
==348== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==348== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==348== Command: ./test
==348== 
==348== 
==348== HEAP SUMMARY:
==348==     in use at exit: 188 bytes in 13 blocks
==348==   total heap usage: 13 allocs, 0 frees, 188 bytes allocated
==348== 
==348== 188 (104 direct, 84 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==348==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==348==    by 0x1093D8: ft_split (ft_split.c:91)
==348==    by 0x109506: main (ft_split.c:113)
==348== 
==348== LEAK SUMMARY:
==348==    definitely lost: 104 bytes in 1 blocks
==348==    indirectly lost: 84 bytes in 12 blocks
==348==      possibly lost: 0 bytes in 0 blocks
==348==    still reachable: 0 bytes in 0 blocks
==348==         suppressed: 0 bytes in 0 blocks
==348== 
==348== For lists of detected and suppressed errors, rerun with: -s
==348== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

아마 메모리를 할당하는 malloc 부분에서 잘못된 메모리를 접근한 것 같은데 저는 도대체 어떤 부분에서 문제가 발생한건지 모르겠습니다.
조언 부탁드립니다

라스코니의 이미지

dump 파일(없으면 생성되도록 설정해서)을 가지고 gdb로 debug를 해보세요.
아마 아래와 같이 하면 될 겁니다.
gdb 실행파일명 dump파일명
bt
frame 0

자세한 건 google에게 물어보세요.

익명 사용자의 이미지

메모리 leak 은 malloc 으로 할당해 사용하고 해제를 안하면 발생하잖아요.
위에 코드를 보면 메모리 해제를 ft_splitfree 함수에서 하고 있는데
gdb 에서 break point 를 ft_splitfree 함수에 걸고 실행해보면 한번도 stop 이 되지않아요.
다시말해서 메모리 해제가 전혀 안되고 있다는거죠.
C 잘하려면 코딩하는것 만큼이나 gdb 사용을 잘해야 되요.

ymir의 이미지

위 코드 돌려봐도 별 문제는 없어 보이는데요..
memory leak 은 main 에서 종료할 때 char **test 해제 안 해줘서 그런거니, 그거 free 해주면 될 거고..
정말로 segfault 가 떨어졌다면, 실제 문제가 생긴 부분은 다른 데에 있을 겁니다.

그럴 때는 "ulimit -c unlimited" 쳐서 core dump 생성되도록 하고..
실행파일 실행한 후에, segfault 떨어지면 core 파일이 있을 겁니다.
"gdb 실행파일 core" 실행한 후에..
gdb 프롬프트에서 "bt" 라고 치면 어디서 죽었는지 알 수 있을 겁니다.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.