-2

我有这个目录树:

xy@xy:/test# find .
.
./2
./2/Asd
./2/Asd/qwe
./2/Asd/qwe/txt.txt
./1

在“test”文件夹中可以有更多的目录,如 4、5、6,但 asd、Asd、ASD、qwe、Qwe、QWE 是不变的。目的是计算所有可能的路径,如下所示:

/test/1/ASD/QWE/txt.txt
/test/2/asd/qwe/txt.txt
/test/2/Asd/Qwe/txt.txt

然后读取文件(txt.txt)

我创建了(复制并粘贴在一起......)以下内容,它正在工作一段时间。我标记了我有问题的行。

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <stdlib.h>

char *filetosearch="txt.txt";
char *test="/test/";
char *slash="/";
char *directory[3][3] = {{"asd", "Asd", "ASD"}, {"qwe","Qwe","QWE"}};
int dircounter1=0;
int dircounter2=0;
FILE *filetosf;
char **dirpatharr=NULL;
int dirpathcount=0;
char **hdarr=NULL;
int hdarrcount=0;
char **fullpath=NULL;
int count,size;
char *dirname;
DIR  *d;
struct dirent *dir;
int main(void)
{
    d = opendir(test);
    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            if( dir->d_type==DT_DIR )
            {
                dirname=dir->d_name;
                if((strcmp( dirname, ".." ) == 0) || (strcmp( dirname, "." ) == 0) )
                {
                }
                else
                {
                    hdarr=(char **)realloc(hdarr,(hdarrcount+1)*sizeof(dirname));
                    hdarr[hdarrcount]=dirname;
                    hdarrcount++;
                }
            }
            else
            {
            }
        }
    }

    closedir(d);

    for (count=0; count<hdarrcount; count++ )
    {
        for (dircounter1 = 0; dircounter1 < 3; dircounter1++ )
        {
            for (dircounter2 = 0; dircounter2 < 3; dircounter2++ )
            {
                fullpath = malloc ( strlen(test) + strlen(hdarr[count]) + strlen(slash) + strlen(directory[0][dircounter2]) + strlen(slash) + strlen(directory[1][dircounter1]) + strlen(slash) + strlen(filetosearch)+1);
                strcpy (fullpath,test);
                strcat (fullpath,hdarr[count]);
                strcat (fullpath,slash);
                strcat (fullpath,directory[0][dircounter2]);
                strcat (fullpath,slash);
                strcat (fullpath,directory[1][dircounter1]);
                strcat (fullpath,slash);
                strcat (fullpath,filetosearch);

                printf("fullpath:%s\n",fullpath);
                //    filetosf = fopen(fullpath,"r");  //THIS WILL BE THE PROBLEM!!!!

                if (filetosf){
                    fseek (filetosf, 0L, SEEK_END);
                    size=ftell(filetosf);
                    fclose(fullpath);
                    printf("file exist:%s\n",fullpath);
                }
                free (fullpath);
            }
        }
    }
}

- - - -剪这里 - - - - - - - - - -

它有这个输出(就像我想要的那样):

fullpath:/test/2/asd/qwe/txt.txt
fullpath:/test/2/Asd/qwe/txt.txt
fullpath:/test/2/ASD/qwe/txt.txt
fullpath:/test/2/asd/Qwe/txt.txt
fullpath:/test/2/Asd/Qwe/txt.txt
fullpath:/test/2/ASD/Qwe/txt.txt
fullpath:/test/2/asd/QWE/txt.txt
fullpath:/test/2/Asd/QWE/txt.txt
fullpath:/test/2/ASD/QWE/txt.txt
fullpath:/test/1/asd/qwe/txt.txt
fullpath:/test/1/Asd/qwe/txt.txt
fullpath:/test/1/ASD/qwe/txt.txt
fullpath:/test/1/asd/Qwe/txt.txt
fullpath:/test/1/Asd/Qwe/txt.txt
fullpath:/test/1/ASD/Qwe/txt.txt
fullpath:/test/1/asd/QWE/txt.txt
fullpath:/test/1/Asd/QWE/txt.txt
fullpath:/test/1/ASD/QWE/txt.txt

但是当我删除备注符号并激活文件打开部分filetosf = fopen(fullpath,"r"); 时,我无法读取文件。当我检查输出时,我得到了这个:

fullpath:/test/2/asd/qwe/txt.txt
fullpath:/test//Asd/qwe/txt.txt
fullpath:/test//ASD/qwe/txt.txt
fullpath:/test//asd/Qwe/txt.txt
fullpath:/test//Asd/Qwe/txt.txt
fullpath:/test//ASD/Qwe/txt.txt
fullpath:/test//asd/QWE/txt.txt
fullpath:/test//Asd/QWE/txt.txt
fullpath:/test//ASD/QWE/txt.txt
fullpath:/test//asd/qwe/txt.txt
fullpath:/test//Asd/qwe/txt.txt
fullpath:/test//ASD/qwe/txt.txt
fullpath:/test//asd/Qwe/txt.txt
fullpath:/test//ASD/Qwe/txt.txt
fullpath:/test//asd/QWE/txt.txt
fullpath:/test//Asd/QWE/txt.txt
fullpath:/test//ASD/QWE/txt.txt

如果我在推荐之前打印出这些行,甚至会发生这种情况fopen。为什么会这样?

我不是一个经验丰富的程序员,所以请尽量简单地解释一下。

4

2 回答 2

2

在这段代码中的许多奇怪之处中,明显的直接错误是:

fullpath = malloc ( strlen(test) + strlen(hdarr[count]) + strlen(slash) + strlen(directory[0][dircounter2]) + strlen(slash) + strlen(directory[1][dircounter1]) + strlen(slash) + strlen(filetosearch)+1);

然后是一堆字符串副本,例如:

strcpy (fullpath,test);

注意:fullpath声明如下:

char **fullpath = NULL;

其中声明了一个指向字符指针的指针;不是指向字符的指针。尝试打开警告,然后在正确声明此变量后重新检查使用此变量的每个地方:

char *fullpath = NULL;

接下来,您保存(我松散地使用该术语)您正在构建的目录名称:

dirname=dir->d_name;
...
hdarr[hdarrcount]=dirname;

但这只是将 d_name 地址保存到 hdarr 动态数组中的新插槽中。一旦您再次调用 readdir()(或 closedir()),该地址就无效了。从readdir()文档中:

readdir() 返回的数据可能会被后续对同一目录流的 readdir() 调用覆盖。

因此,您存储的所有这些指针都在实现拥有的内存中,它可以在任何时候/以任何方式认为合适的时候完全自由地爆炸。如果你想保留它们,你需要制作它们的副本(当然,当你完成时 free() 这些副本)。

如何解决此问题:

我通常不推荐这个,但在你的情况下,我会:在目录名上使用 strdup() 。这是一个穷人“为我分配一个大小与该缓冲区相同的字符串缓冲区,包括空项的空间,复制字符串,并将指针返回给我。所以你的代码将如下所示:

else
{
    char **pp = realloc(hdarr,(hdarrcount+1)*sizeof(*pp));
    if (pp)
    {
        hdaerr = pp;
        hdarr[hdarrcount++] = strdup(dir->d_name);
    }
    else
    {   // panic ensues
        exit(EXIT_FAILURE);
    }
}

不要忘记正确释放它。hdarr 中的每个字符串指针都是动态分配的。确保释放它们,然后释放阵列本身。代码的尾部(就在退出之前)应如下所示:

for (i=0;i<hdarrcount;i++)
    free(hdarr[i]);
free(hdarr);  

次要但重要:

永远不要这样做:

hdarr=(char **)realloc(hdarr,(hdarrcount+1)*sizeof(dirname));

如果realloc()失败,它将返回 NULL 并且您只是丢失(并因此泄漏)您是原始数据指针。改为这样做:

char **pp = realloc(hdarr,(hdarrcount+1)*sizeof(*pp));
if (pp)
{
    hdaerr = pp;
    // .. continue with the rest of your assignment code
}
else
{   // allocation error, but at least you still have the 
    // old hdaerr so you can free it.
}

接下来,正如其他人指出的那样:

fclose(fullpath);

这是完全错误的。fclose()期望 a FILE *,而不是 char **。将您之前打开的 filetosf 传递给它(通过打开,我的意思是在取消注释您当前取出的问题行之后。一旦您这样做了:

fclose(filetosf);

注意:在您这样做之前,通过 fclose() 代码行注释掉所有fopen。因为他们击中 NULL 文件指针是再一次与我们说它... undefined

于 2012-11-09T21:29:59.657 回答
0

这是错误的:

fclose(fullpath);
于 2012-11-09T21:09:42.303 回答