Плохое поведение с strcat

Я реализовал следующую функцию для копирования каталогов.

int copy_dir(char *source, char *destination, char *file_name)
{
    DIR *dir_ptr = NULL;
    struct dirent *direntp;
    char temp_dest[strlen(destination)+1];
    char temp_src[strlen(source)+1];
    strcat(destination, "/");
    strcat(source, "/");
    strcpy(temp_dest, destination);
    strcpy(temp_src, source);

    ...

    if( (dir_ptr = opendir(source)) == NULL )
    {
        fprintf(stderr, "Cannot open %s for copying\n", source);
        return ERR_OPEN_DIR;
    }
    else
    {
        while(direntp = readdir(dir_ptr))
        {     
            // File must already be on the USB key
            if(strcmp(direntp->d_name,file_name) == 0)
            {               
                strcat(temp_dest, direntp->d_name);
                printf("after strcat temp_dest=%s\n", temp_dest);         
                strcat(temp_src, direntp->d_name);
                printf("after strcat temp_src=%s\n", temp_src); 
                printf("destination:%s\n",temp_dest);
                copy_files(temp_src, temp_dest); 
            }
        }
    }
    closedir(dir_ptr);
    return 1;
} 

Я хотел бы понять, почему следующая реализация

strcat(temp_dest, direntp->d_name);
printf("after strcat temp_dest=%s\n", temp_dest);         
strcat(temp_src, direntp->d_name);
printf("after strcat temp_src=%s\n", temp_src); 
printf("destination:%s\n",temp_dest);
copy_files(temp_src,temp_dest);

возвращает:

after strcat temp_dest=/tmp/usb/test10
after strcat temp_src=/media/sda1/test10
destination:10

Почему 10 возвращается не /tmp/usb/test10 через последний printf?

1 ответ

Решение

Вот ваша главная проблема, сначала вы не должны изменять char *source а также char *destination потому что вы не знаете, достаточно ли места выделено для добавления символа, и strcat не выделяет его для вас, но самая важная ошибка заключается в следующем

Сначала вы объявляете эти массивы для хранения strlen(string) + 1 символы, что на самом деле означает, что вы можете скопировать в них только одну и ту же строку, так как вам нужен один дополнительный символ для завершения '\0' байт, который не учитывается strlen

char temp_dest[strlen(destination)+1];
char temp_src[strlen(source)+1];

затем вы добавляете еще один символ в строку, этот не был посчитан strlen, так что теперь строка не будет соответствовать вашему массиву, а также, вы не знаете, если destination а также source есть достаточно места для еще одного персонажа.

strcat(destination, "/");
strcat(source, "/");

и, наконец, вы копируете строку

strcpy(temp_dest, destination);
strcpy(temp_src, source);

Я предлагаю вам сделать это так

size_t dest_length = strlen(destination);
size_t src_length = strlen(source);
char temp_dest[dest_length+2];
char temp_src[scr_length+2];

temp_dest[dest_length] = '/';
temp_src[src_length] = '/';
temp_dest[1 + dest_length] = '\0';
temp_src[1 + src_length] = '\0';

memcpy(temp_dest, destination, dest_length);
memcpy(temp_src, source, src_length);
Другие вопросы по тегам