C程序:生成目录,链接损坏

C程序:生成目录,链接损坏,c,C,我的C程序中有一个非常奇怪的问题,我不知道如何将代码裁剪到所需的程度,但我会尝试。 因此,我生成了一组这种结构的目录和子目录: AA/--和子目录:0/,1/,2/。。。 BB也一样/ 我是这样做的: char *my_location = "/Users/example/Documents/"; int total = 2; int i, j, total_subDir; char ***file_location; total_subDir = 100; file_location = ma

我的C程序中有一个非常奇怪的问题,我不知道如何将代码裁剪到所需的程度,但我会尝试。 因此,我生成了一组这种结构的目录和子目录:

AA/--和子目录:0/,1/,2/。。。 BB也一样/

我是这样做的:

char *my_location = "/Users/example/Documents/";
int total = 2;
int i, j, total_subDir;
char ***file_location;
total_subDir = 100;
file_location = malloc(sizeof(char**)* total);
char *suffix = "AA/"; char *suffix2 = "BB/";

int my_loc_len = strlen(my_location);

for (i = 0; i < total; i++) {

    char *temp;
    file_location[i] = malloc(sizeof(char*)* total_subDir);
    temp = malloc(sizeof(char)* (my_loc_len + 4));
    memcpy(temp, my_location, my_loc_len);
    if (i == 0) memcpy(&temp[my_loc_len], suffix, 3);
    else memcpy(&temp[my_loc_len], suffix2, 3);

    temp[my_loc_len + 3] = '\0';
    int temp_length = strlen(temp);
    mkdir(temp, 0777);

    for (j = 0; j < total_subDir; j++) {
        char *subdir_name;

       subdir_name = malloc(sizeof(char)* 20);
        sprintf(subdir_name, "%d", j);
        int digit_num = strlen(subdir_name);

       file_location[i][j] = malloc(sizeof(char) *(temp_length + digit_num + 1 + 1));
        memcpy(file_location[i][j], temp, temp_length);
        memcpy(&file_location[i][j][temp_length], sub_dir_name, digit_num);
        memcpy(&file_location[i][j][temp_length + digit_num], "/", 1);

        file_location[i][j][temp_length + digit_num + 1] = '\0';

        mkdir(file_location[i][j], 0777);
        free(subdir_name);
    }
    free(temp);
}
其中location是其中一个子目录,因此:file_location[i][j];所以我从不改变链接

然而,有时目录的链接会被破坏,所以我会得到类似于“/Users/ex1mple/Documents/”的东西,通常只在一个链接中。当我使用相同的数据多次重新运行我的程序时,有时会出现损坏的文件,有时则不是,并且不总是相同的链接


我想我的问题没有一个答案,我想我在某处有一些内存写入/问题,但我无法重建它的位置。我运行valgrind在我的代码,他也没有找到任何东西。有人可能知道我如何检索错误,有什么建议吗?

您可以通过正确使用
宏来改进代码,避免
memcpy
,不必要的
malloc
,使用通用
函数
,并为上述任务引入
错误检查

下面的代码执行您预期的任务

#define SUBDIR          100
#define PERMISSION      0777
#define PARENT_PATH     "/Users/example/Documents/"

/* Function to create Directories */
void create_dir (char *file_name, int PERM)
{
    printf("Creating Directory : [%s]\n", file_name);
    if (-1 == mkdir(file_name, PERM)) {
        fprintf(stderr, "Error in mkdir: [%d][%s]\n", errno, strerror(errno));
        exit(EXIT_FAILURE);
    }
    return;
}


我认为Saurabh Meshram的解决方案是首选方案。我仍然想展示这个版本,只是为了向询问者说明,他的代码可能是什么样子,只需删除不必要的
mallocs
,并使用字符串操作而不是
memcpy
。我认为可读性已经大大提高了

#define LOCATION_MAXLEN 50
#define SUFFIX_MAXLEN   5
#define NUMBER_MAXLEN   5
#define TOTAL           2
#define TOTAL_SUBDIR    100
#define PERMISSION      0777

...

char *my_location = "/Users/example/Documents/";
int i, j;
char file_location[TOTAL][TOTAL_SUBDIR][LOCATION_MAXLEN];

char* suffix1 = "AA/",
    * suffix2 = "BB/";

for (i = 0; i < TOTAL; i++) {

    char temp[LOCATION_MAXLEN+SUFFIX_MAXLEN];
    strcpy_s(temp, my_location);
    strcat_s(temp, i == 0 ? suffix1 : suffix2);

    mkdir(temp, PERMISSION);

    for (j = 0; j < TOTAL_SUBDIR; j++) {
        char subdir_name[NUMBER_MAXLEN];
        sprintf_s(subdir_name, "%d", j);
        int digit_num = strlen(subdir_name);

        strcpy_s(file_location[i][j], temp);
        strcat_s(file_location[i][j], subdir_name);
        strcat_s(file_location[i][j], "/");

        mkdir(file_location[i][j], PERMISSION);
    }
}
#定义位置_maxlen50
#定义后缀_MAXLEN 5
#定义数字\u最大值5
#定义总计2
#定义总细分100
#定义权限0777
...
char*my_location=“/Users/example/Documents/”;
int i,j;
字符文件位置[TOTAL][TOTAL][SUBDIR][location\u MAXLEN];
char*suffix1=“AA/”,
*后缀x2=“BB/”;
对于(i=0;i
在字符串操作中使用memcpy有什么特别的原因吗?那代码太可怕了。所有那些
memcpy
调用让我毛骨悚然。我想整理一下,使用字符串函数,然后盘点一下。对于这类东西来说,C是一种令人讨厌的语言。你不能用更合适的吗。您也不应该编写
sizeof(char)
。根据定义,等于1。我同意@DavidHeffernan对该代码的观点。您的一些
malloc
s是完全冗余的。如果数组是固定长度的,那么只需在堆栈上分配它。还有,这些常量字符串。试着在函数开始时把它们放在一个地方。事实上,为了“向我们保证”您不会试图更改它们(因为在代码中很难遵循它们),请将它们定义为宏。如果将单个字符写入字符串,则不要使用
memcpy
。那么,除了sizeof(char)之外,我应该写些什么,如何为char数组分配内存?如果我将其更改为字符串操作,则不会更改任何内容,我避免使用它们,因为它们会对终端符号进行冗余搜索,如果我知道它在哪里,避免这个很好,这看起来真的很好,谢谢。当我必须将多个字符串连接到另一个字符串上时,sprintf是要使用的方法吗?
sprintf
将打印到一个字符串,因此您可以使用它将字符串(本例中的路径)与
/
分隔符连接起来。适当使用
函数
将减少您的代码,使其更易于阅读/理解和简单。添加错误检查将使代码易于调试。
int main (int argc, char **argv)
{
    if (argc != 2)
    {
        if (1 == argc) {
            fprintf(stderr, "Usage : %s <NO_OF_SUBDIR>\n", argv[0]);
            exit(EXIT_FAILURE);
        }
    }

    if (atoi(argv[1]) > 26) {
         fprintf(stderr, "Value should be lesser than 26 (A-Z)\n");
         exit(EXIT_FAILURE);
    }

    int i, j, suffix = 65;               /* ASCII value for A is 65 */

    /* Filename not to exceed 1024 characters */
    char *temp = malloc (sizeof(char) * 1024);      

    for (i=0; i<atoi(argv[1]); i++)
    {       
        sprintf(temp, "%s/%c/", PARENT_PATH, suffix);           

        /* Creates Directory, ex: For input 1, creates dir A*/
        create_dir(temp, PERMISSION);   
        for (j=0; j<SUBDIR; j++)
        {
            /* Creates Sub-directory ex: /A/0 .. /A/99/ */
            sprintf(temp, "%s/%c/%d", PARENT_PATH, suffix, j);
            create_dir(temp, PERMISSION);
        }
        /* Increments to ASCII of next Alphabet */ 
        suffix++;
    }       
    free(temp);
    return 0;          
}
$ gcc -o exe 2.c -Wall -Wextra
$ ./exe 1          /* Creates dir A, with 0-99 sub directories */
$ ./exe 2          /* Creates dir A and B, with 0-99 sub directories in each */
$ ./exe 26         /* Creates dir A to Z,  with 0-99 sub directories in each */
$ ./exe 27
Value should be lesser than 27 (A-Z)
#define LOCATION_MAXLEN 50
#define SUFFIX_MAXLEN   5
#define NUMBER_MAXLEN   5
#define TOTAL           2
#define TOTAL_SUBDIR    100
#define PERMISSION      0777

...

char *my_location = "/Users/example/Documents/";
int i, j;
char file_location[TOTAL][TOTAL_SUBDIR][LOCATION_MAXLEN];

char* suffix1 = "AA/",
    * suffix2 = "BB/";

for (i = 0; i < TOTAL; i++) {

    char temp[LOCATION_MAXLEN+SUFFIX_MAXLEN];
    strcpy_s(temp, my_location);
    strcat_s(temp, i == 0 ? suffix1 : suffix2);

    mkdir(temp, PERMISSION);

    for (j = 0; j < TOTAL_SUBDIR; j++) {
        char subdir_name[NUMBER_MAXLEN];
        sprintf_s(subdir_name, "%d", j);
        int digit_num = strlen(subdir_name);

        strcpy_s(file_location[i][j], temp);
        strcat_s(file_location[i][j], subdir_name);
        strcat_s(file_location[i][j], "/");

        mkdir(file_location[i][j], PERMISSION);
    }
}