2012-12-19 5 views
4

C 코드를 작성하여 C 파일의 모든 함수를 찾고 해당 함수 이름을 인쇄하고 싶습니다.C : 함수 이름을 찾는 중 세그먼트 오류 (코어 덤프)

내 코드는 다음과 같습니다

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

#define SIZE 1024 
void ffname(char *line) 
{ 
    int i=1,j=0; 
    char *dt; 
    char *name; 
    strtok(line,"("); 
    dt = strchr(line,' '); 
    if(dt[i] == '*') 
     i++; 
    while(dt[i] != '\0') 
    { 
     name[j]=dt[i]; 
     i++; 
     j++; 
    } 
    name[j] ='\0'; 
    printf("Function name is: %s\n", name); 
} 

int main(int argc, char **argv) 
{ 
    if(argc < 2) 
    { 
     printf("Give the filename \n"); 
     printf("Usage: %s filename\n", argv[0]); 
     return -1; 
    } 
    int i, lines =0, funlines =0,count =0, fn =0, flag =0; 
    char c[100],b[100]; 
    FILE *fd; 
    fd = fopen(argv[1],"r"); 
    while(fgets(c,SIZE,fd)) 
    { 
     lines++; 
     i=0; 
     for(i=0;i<strlen(c);i++) 
     { 
      while(c[i] =='\t' || c[i] == ' ') 
      { 
       i++; 
      } 
      if(c[i] == '{') 
      { 
       count++; 
       if(flag) 
       { 
        funlines++; 
       } 
       if(count == 1) 
       { 
        fn++; 
        printf("Function %d is Started..............\n", fn); 
        flag = 1; 
        ffname(b); 
       } 
       break; 
      } 
      else if(c[i] == '}') 
      { 
       count--; 
       if(!count) 
       { 
        flag = 0; 
        printf("No of lines in the function %d is: %d\n", fn, funlines); 
        printf("Function %d is finished..........\n", fn); 
        funlines = 0; 
       } 
       else 
       { 
        funlines++; 
       } 
       break; 
      } 
      else if(flag) 
      { 
       funlines++; 
       break; 
      } 
     } 
     strcpy(b,c); 
    } 
    printf("Total no of fucnion%d\n",fn); 
    printf("Total no of lines%d\n",lines); 
    return 0; 
} 

내가 입력으로 다음과 같은 C 파일을 제공

,

#include<stdio.h> 
void add() 
{ 
    int a=5,b=7; 
    printf("Addition is:%d\n", a+b); 
} 
void sub() 
{ 
    int a=20,b=8; 
    printf("Subtraction is:%d\n", a-b); 
} 
void main() 
{ 
    char *name="dhahira dhasneem"; 
    char *line; 
    line=strchr(name,' '); 
    printf("Line:%s\n",line); 
    printf("Name:%s\n",name); 
    add(); 
    sub(); 
} 

나는 다음과 같은 출력을 얻을.

Function 1 is Started.............. 
Segmentation fault (core dumped) 

나는 valgrind를 사용하지만, 나는 그와 함께 오류를 확인하는 방법을 모르겠어요. 나를 안내 해줘. 고맙습니다.

업데이트 : 내가 대답을 제안 사용 I 출력을 가지고

. 그런 다음 함수의 세부 정보 (함수 이름 및 함수 깊이)를 구조에 저장하는 이전 코드를 확장하고 싶습니다. 나는 간단한 프로그램을위한 함수의 세부 사항을 저장할 때 출력을 얻고 있었다. 그러나 나는이 프로그램을 gdb에서 실행할 때 다음과 같은 결과를 얻고있다.

(gdb) b 87 
Breakpoint 1 at 0x804885e: file fun_printstruct.c, line 87. 
(gdb) r dat.c 
Starting program: /home/dhahira/dhas/Project/a.out dat.c 
Function 1 is Started.............. 

Program received signal SIGSEGV, Segmentation fault. 
0x080485d4 in ffname (line=0xbfffe71c "/*struct *dhahira", name=0x0) 
    at fun_printstruct.c:21 
21   name[j]=dt[i]; 
(gdb) s 

Program terminated with signal SIGSEGV, Segmentation fault. 
The program no longer exists. 

내 코드는 다음과 같습니다

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

#define SIZE 1024 
void ffname(char *line) 
{ 
    int i=1,j=0; 
    char *dt; 
    char name[SIZE]; 
    strtok(line,"("); 
    dt = strchr(line,' '); 
    if(dt[i] == '*') 
     i++; 
    while(dt[i] != '\0') 
    { 
     name[j]=dt[i]; 
     i++; 
     j++; 
    } 
    name[j] ='\0'; 
    printf("Function name is: %s\n", name); 
} 

int main(int argc, char **argv) 
{ 
    if(argc < 2) 
    { 
     printf("Give the filename \n"); 
     printf("Usage: %s filename\n", argv[0]); 
     return -1; 
    } 
    int i, lines =0, funlines =0,count =0, fn =0, flag =0, fg=0,size=0,emptyflag=0,commandflag=0; 
    char c[SIZE],b[SIZE],st[SIZE],d[SIZE]; 
    int command[]={}; 
    FILE *fd; 
    fd = fopen(argv[1],"r"); 
    while(fgets(c,SIZE,fd)) 
    { 
     emptyflag=0;  
     lines++; 
     for(i=0;i<(sizeof(command)/4);i++) 
     { 
      if(lines == command[i]) 
      { 
       commandflag=1; 
       break; 
      } 
     } 
     strcpy(st,c); 
     strtok(st," "); 
     size = strlen(c); 
     if(size == 1 && (strcmp(c,"\n"))== 0) 
      emptyflag=1; 
     if(!strcmp(st,"struct")) 
      fg=1; 
     for(i=0;i<size;i++) 
     { 
      if(commandflag) 
      { 
       break; 
      } 
      while(c[i] =='\t' || c[i] == ' ') 
      { 
       i++; 
      } 
      if(c[i] == '{') 
      { 
       count++; 
       if(flag) 
       { 
        if(!emptyflag) 
         funlines++; 
        else 
         emptyflag=0; 
       } 
       if(count ==1 && fg ==1) 
       { 
        if(b[strlen(b)-2] == ')') 
        { 
         fn++; 
         printf("Function %d is Started..............\n", fn); 
         flag = 1; 
         ffname(b); 
        } 
        else 
        { 
         count--; 
        } 
       } 
       else if(count == 1) 
       { 
        fn++; 
        printf("Function %d is Started..............\n", fn); 
        flag = 1; 
        ffname(b); 
       } 
       break; 
      } 
      else if(c[i] == '}') 
      { 
       count--; 
       if(count ==0 && fg ==1) 
       { 
        flag = 0; 
        printf("No of lines in the function %d is: %d\n", fn, funlines); 
        printf("Function %d is finished..........\n", fn); 
        funlines = 0; 
        fg=0; 
       } 
       else if(count ==0) 
       { 
        flag = 0; 
        printf("No of lines in the function %d is: %d\n", fn, funlines); 
        printf("Function %d is finished..........\n", fn); 
        funlines = 0; 
       } 
       else if(count == -1) 
       { 
        count=0; 
        fg=0; 
       } 
       else 
       { 
        if(!emptyflag) 
         funlines++; 
        else 
         emptyflag=0; 
       } 
       break; 
      } 
      else if(flag ==1 && fg==1) 
      { 
       if(!emptyflag) 
        funlines++; 
       else 
        emptyflag=0; 
       break; 
      } 
      else if(flag) 
      { 
       if(!emptyflag) 
        funlines++; 
       else 
        emptyflag=0; 
       break; 
      } 
      break; 
     } 
     if(commandflag == 1) 
      commandflag = 0; 
     else 
      strcpy(b,c); 
    } 
    printf("Total no of fucnion%d\n",fn); 
    printf("Total no of lines%d\n",lines); 
    return 0; 
} 

이 문제에서 극복하기 위해 나를 인도 해주십시오 (구조로 기능 정보를 저장하기위한 확장).

이 문제는 코드를 확장하는오고있다 (I 별도로 올바른 출력을 얻을 수 있습니다.)

+5

GDB를 사용하여 시작하면, 오류를 일으키는 행이 표시됩니다. –

+1

그리고'gcc -Wall -g'로 컴파일하고 경고가 나오지 않을 때까지 코드를 개선하는 습관을 얻으십시오. 그런 다음'gdb'와'valgrind'를 사용하여 프로그램을 디버그하십시오. –

+1

또한'char * name = "foo";는 ** 잘못되었습니다. ** char name [] = "foo";'또는'const char * name = "foo"; –

답변

4

을 당신은 길이의 배열로 읽어 후 1024 SIZE를 선언하고있다 (100) :

#define SIZE 1024 
// ... snip .... 
    char c[100],b[100]; 
    FILE *fd; 
    fd = fopen(argv[1],"r"); 
    while(fgets(c,SIZE,fd)) 

이것은 배열의 경계를 넘어 스택의 나머지 부분에 잘 쓰고 손상을 초래한다는 것을 의미합니다. 이 경우 입력 파일의 모든 행이 100 자 미만이기 때문에 실제로는 실제로 발생하지 않지만 누군가가 긴 줄이있는 파일을 전달한 경우에 발생할 수 있습니다.

이 중

char c[SIZE],b[SIZE]; 

수 또는 fgets() 호출에 sizof()을 사용해야합니다

fgets(c,sizeof(c),fd) 

다른 사람들이 지적했듯이 가능한 모든 경고를 켤 경우, 그것은 최선의 방법; 이것은 당신이 오류를 더 빨리 잡는 데 도움이 될 것입니다. GCC 또는 Clang에서 나는 -Wall -Wextra -Werror을 추천 할 것이다; 이렇게하면 모든 일반적인 경고가 활성화되고 경고는 오류로 간주되어 무시할 수 없게됩니다. , 두 번째는 심각한 문제가되지 않습니다

sf.c:16:9: error: variable 'name' is uninitialized when used here 
     [-Werror,-Wuninitialized] 
     name[j]=dt[i]; 
     ^~~~ 
sf.c:9:15: note: initialize the variable 'name' to silence this warning 
    char *name; 
      ^
       = NULL 
sf.c:40:18: error: comparison of integers of different signs: 'int' and 'size_t' 
     (aka 'unsigned long') [-Werror,-Wsign-compare] 
     for(i=0;i<strlen(c);i++) 
       ~^~~~~~~~~~ 

을 그냥 던져 또는 부호 i를 선언; 나는 당신의 코드에 그것을 실행하는 경우, 또한 다음과 같은 경고를 얻을 수 너 먼저 고쳐야 해. 스택에 이름 ​​(char name[SIZE]; 또는 유사) 또는 동적으로 (char *name = malloc(strlen(line)); 또는 이와 비슷한) 버퍼를 할당해야합니다.있는 그대로, name은 초기화되지 않은 포인터입니다. 메모리의 어느 부분이든 가리킬 수 있으며, name[j]에 내용을 저장하여 역 참조를 시도하면 유효하지 않은 메모리 영역에 쓰고 segfault를 얻게됩니다.

마지막으로 이러한 문제를 해결 한 후에 다른 문제가 발생하면 디버거에서 실행하고 문제가 발생한 위치를 확인하는 것이 좋습니다. IDE를 사용하고 있다면 아마도 디버거 인터페이스가 내장되어있을 것입니다. 그렇지 않다면 -g으로 컴파일하고 gdb executable arguments을 실행하십시오.

+0

선생님, 나는 지금까지 내가 위에서 언급 한 것과 같은 오류를 얻고 있습니다. – Dhasneem

+0

@Dhas 내 답변을 확장했습니다. 내가 언급 한 첫 번째 버그는 여전히 고쳐 져야하지만 실제로는 100 자보다 긴 입력 줄이 없으면 프로그램을 크래시하지 않을 것입니다. 더 심각한 버그가 있다는 것을 깨달았습니다 :'ffname'에서'name'을 초기화하지 않았습니다. 이것은 초기화되지 않은 포인터를 역 참조하려고한다는 것을 의미합니다. –

+0

"char name [SIZE];"를 사용하면 작동합니다. 당신의 안내에 감사드립니다. – Dhasneem

관련 문제