私はCで円記号のリンクをチェックするプログラムを書いています。戦略は、ファイルのinodeとdevIDを格納するstruct fileInfoを作成することです:Cで奇妙なメモリエラー
typedef struct fileInfo fileInfo;
struct fileInfo {
ino_t inode;
dev_t devID;
};
これらの構造体の配列を作成し、新しいファイルを開く前にそのファイルがすでに存在するかどうかを毎回確認します。もしそうなら、それは循環リンクです。
void func1(...)
{
fileInfo **fileData = malloc(sizeof(struct fileInfo*));
int fileDataLen = 0;
char* path = "path of file";
/* some flags */
func2(path, fileData, &fileDataLen);
for (int i = 0; i < fileDataLen; i++)
free(fileData[i]);
free(fileData);
}
void func2(char* path, fileInfo ** fileData, int * fileDataLen)
{
//try to open file
struct stat buf;
if (openFile(file, &buf, followSymLinks) == -1)
exit(1);
fileData = checkForLoops(fileData, fileDataLen, &buf, file);
if (S_ISDIR(buf.st_mode))
{
char* newPath = /* modify path */
func2(newPath,fileData, fileDataLen);
}
/* other stuff */
}
int openFile(char* file, struct stat * buf, fileInfo ** fileData, int * fileDataLen)
{
if (lstat(path, buf) < 0)
{
fprintf(stderr, "lstat(%s) failed\n", path);
return -1;
}
return 0;
}
fileInfo** checkForLoops(fileInfo **fileData, int * fileDataLen,struct stat *buf,
char* path)
{
for (int i = 0; i < (*fileDataLen); i++)
{
if (fileData[i]->inode == buf->st_ino &&
fileData[i]->devID == buf->st_dev)
fprintf(stderr, "circular symbolic link at %s\n", path);
}
fileInfo *currFile = malloc(sizeof(struct fileInfo));
memcpy(&currFile->inode, &buf->st_ino, sizeof(buf->st_ino));
memcpy(&currFile->devID, &buf->st_dev, sizeof(buf->st_dev));
fileData[(*fileDataLen)] = currFile;
(*fileDataLen)++;
fileData = realloc(fileData, ((*fileDataLen)+1) * sizeof(struct fileInfo*));
return fileData;
}
しかし、func2()をいくつか呼び出した後にメモリリークがあり、fileDataが何も指していないことに気付きました。私はfunc2()で何も解放しないので、漏れがどこから来ているのか分かりません。私は何かがあると仮定していますrealloc
shenanigans、しかし私はなぜ理解していない。ヘルプは非常に高く評価されるだろう!
メモリリークを見つけるために[valgrindの(http://valgrind.org/docs/manual/quick-start.html#quick-start.mcrun)を使用してみてください。参考までに、 'fileData = calloc(sizeof(struct fileInfo *)、n)'を使って配列をあるサイズの 'n 'に初期化する方がはるかに効率的です。次に、配列の空き領域が足りなくなったら、 'n * 2'にreallocします。このようにして、ファイル情報を追加するたびに再割り当てを避けることができます。 – Chris