4

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していますが、それでエラーを特定する方法がわかりません。私を案内してください。ありがとうございました。

アップデート:

提案された回答を使用すると、出力が得られました。その後、関数の詳細 (関数名と関数の深さ) を構造体に格納するために、以前のコードを拡張したいと思います。単純なプログラムの関数の詳細を保存していたときに、出力を取得していました。しかし、これを で実行すると、プログラムに対して次の出力が得られ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;
}

この問題を克服するために私を導いてください。

コードを拡張したためにこの問題が発生していますか? (正しい出力は別に取得できます。)

4

1 に答える 1

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];

または通話で使用sizof()します。fgets()

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++)
                ~^~~~~~~~~~

2 番目は深刻な問題ではありません。キャストするか、iunsigned を宣言するだけです。最初に修正する必要があります。char name[SIZE];スタック上(または同様のもの)または動的( 、またはそのようなもの)に name のバッファを割り当てる必要がありますchar *name = malloc(strlen(line));。そのままでnameは、初期化されていないポインターです。メモリ内の任意の場所を指している可能性があり、何かを に格納して逆参照しようとするとname[j]、無効なメモリ領域に書き込み、セグメンテーション違反が発生します。

最後に、これらの問題を修正したら、さらに問題がある場合は、デバッガーで実行して、問題が発生する場所を確認することをお勧めします。IDE を使用している場合は、おそらくデバッガー インターフェイスが組み込まれています。そうでない場合は、でコンパイルし-g、実行しますgdb executable arguments

于 2012-12-19T06:24:46.427 に答える