ページ 11

Segmentation fault

Posted: 2012年4月16日(月) 21:56
by きなこ餅
やりたいことは指定ディレクトリ以下の拡張子「.c .cpp .h」ファイルから
指定した文字列が出てくるファイル名と行数を取得し表示したいと思っています。

途中までファイルが全部表示されてしまい、最後にはSegmentation faultが出てしまいます。
どこがおかしいのか教えてください。

また、よろしければ、より効率よく実行できるような技術があれば助言していただけるとありがたいです。

よろしくお願いします。

開発環境
Mac OSX
gcc

コード:

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>

int _search(char *, char *);

int main(int argc, char *argv[])
{
	char path[1024];
	char word[1024];
	int i;
	
	printf("\n\n"
		"************************************************\n"				
		"*		Word Search 〜Ver.1.0〜\n"
		"************************************************\n");
		
	if(argc <= 1)
	{
		strcpy(path,".");
	}
	else
	{
		for(i=1; i<argc; i++)
		{
			if(strcmp(argv[i],"-l") == 0)
			{
				if(strcmp(argv[i+1],"") != 0)
				{
					strcpy(path,argv[i+1]);
				}
				else
				{
					printf("Option ERROR!!\n");
					return 0;
				}
			}
			else if(strcmp(argv[i],"-w") == 0)
			{
				if(strcmp(argv[i+1],"") != 0)
				{
					strcpy(word,argv[i+1]);
				}
				else
				{
					printf("Option ERROR!!\n");
					return 0;
				}
			}
		}
	}
	
	if(strcmp(path,"") == 0)
	{
		strcpy(path,".");
	}

	_search(path,word);
	return 0;
}

int _search(char *path, char *word)
{
	struct stat st;
	struct dirent *dp;
	
	char *get_path;
	char *get_word;
	char *ex;
	char dir_file[1024];
	char next_dir[1024];
	char buf[1024];
	char check_buf[1024];
	char file_dir[1024];
	
	int i,x;
	
	mode_t m;
	FILE *fp;
	DIR *dir;

	get_path = path;
	get_word = word;
		
	dir = opendir(get_path);
	
	if(dir == NULL)
	{
		printf("Directory open ERROR!!\n");
		printf("%s",get_path);
		return 0;
	}
	
	for(dp=readdir(dir); dp!=NULL; dp=readdir(dir))
	{
		sprintf(dir_file,"%s",dp->d_name);
		
		stat(dir_file,&st);

		m = st.st_mode;
				
		if(S_ISREG(m))
		{
			ex = strstr(dir_file,".");
			
			if((strcmp(ex,".c") == 0) || (strcmp(ex,".cpp") == 0) || (strcmp(ex,".h") == 0))
			{
				sprintf(file_dir,"%s/%s",path,dir_file);
			
				fp = fopen(file_dir,"r");
				if(fp == NULL)
				{
					printf("File open ERROR!!\n");
					return 0;
				}
			
				x = 1;
				
				while((fgets(buf,1024,fp)) != NULL)
				{
					sprintf(check_buf,"%s",buf);
					
					if(strpbrk(check_buf,get_word) != NULL)
					{
						printf("%s : %d \"%s\"",file_dir,x,check_buf);
					}
					x++;
				}
			
				fclose(fp);			
			}
		}
		
		if(S_ISDIR(m))
		{
			if((strcmp(dir_file,".") != 0) && (strcmp(dir_file,"..") != 0))
			{
				sprintf(next_dir,"%s/%s",path,dir_file);
				
				_search(next_dir,get_word);
			}
		}
	}
	closedir(dir);
	
	printf("\n");

	return 0;
}

Re: Segmentation fault

Posted: 2012年4月17日(火) 00:38
by softya(ソフト屋)
まず問題は、strpbrkだと単語ではなく一部の文字が一致するだけでNULLじゃ無くなってしまいます。
strstrとかを使われたほうが良いでしょう。
あとSegmentation faultはwindows上のcygwinでは再現されませんでした。

Re: Segmentation fault

Posted: 2012年4月17日(火) 06:22
by きなこ餅
softya(ソフト屋) さんが書きました: あとSegmentation faultはwindows上のcygwinでは再現されませんでした。
環境に依存していると言うことでしょうか?

Re: Segmentation fault

Posted: 2012年4月17日(火) 08:19
by beatle
gdbを使ってデバッグすると、原因の箇所はすぐに見つかるのではないかと思います。
ファイヤープロジェクト GDBが個人的に分かりやすい解説になっておりますので参考にしてください。
ブレークポイントを怪しそうな部分の直前に設定し、runするだけでもデバッガを使う価値があります。(一番最初は何もブレークポイントを設定せずにrunし、セグメンテーション違反が発生することを確認してください)
きなこ餅 さんが書きました:
softya(ソフト屋) さんが書きました: あとSegmentation faultはwindows上のcygwinでは再現されませんでした。
環境に依存していると言うことでしょうか?
もちろん環境に依存するでしょうね。そもそも実行する環境ごとにディレクトリに存在するファイルの数さえ違うのですから。

Re: Segmentation fault

Posted: 2012年4月17日(火) 10:19
by h2so5
Mac OS X 10.7 64bit で実行してみましたが、
108行目でstrcmpにNULLポインタが渡された時点で落ちました。

strstrの戻り値をチェックする必要があります。