繁体   English   中英

memmove留下垃圾 - C.

[英]memmove leaving garbage - C

我编写了以下函数将给定的完整路径拆分为目录,文件名和扩展名。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct path_info {
    char *directory;
    char *filename;
    char *extension;
};

#ifdef WIN32
const char directory_separator[] = "\\";
#else
const char directory_separator[] = "/";
#endif

struct path_info* splitpath(const char *full_path)
{
    size_t length = strlen(full_path);
    struct path_info *p = (struct path_info*) malloc(sizeof(struct path_info) + length + 3);  /* Extra space for padding and shifting */
    if(p)
    {
        char *path = (char *) &p[1];    /* copy of the path */
        char *end = &path[length + 1];  
        char *extension;
        char *last_separator;

        /* copy the path */
        strcpy(path, full_path);
        *end = '\0';
        p->directory = end;
        p->extension = end;
        p->filename  = path;

        last_separator = strrchr(path, directory_separator[0]);    /* Finding the last directory separator */
        if(last_separator) {
            memmove(last_separator + 1, last_separator, strlen(last_separator));  /* inserting a directory separator where null terminator will be inserted */
            p->directory = path;
            *(++last_separator) = '\0';      /* Truncate the directory path */
            p->filename = ++last_separator;  /* Taking the remaining as file name */
        }

        /* Finding the extension starts from second character. This allows handling filenames 
           starts with '.' like '.emacs'.*/
        extension = strrchr(&p->filename[1], '.');
        if(extension) {

            /* shifting the bytes to preserve the extension */
            memmove(extension + 1, extension, strlen(extension));   /* problem happens here */
            p->extension = extension + 1;

            *extension = '\0';  /* Truncates the file name */
        }
    }
    return p;
}


int main(void)
{
    struct path_info *p = splitpath("C:\\my documents\\some.txt");
    printf("Directory : %s\n", p->directory);
    printf("Filename : %s\n", p->filename);
    printf("Extension : %s\n", p->extension);
    return 0;
}

这适用于GCC上的给定输入。 但它在MSVC上失败,在extension变量上留下了一些垃圾数据。 我已经对出错的地方添加了评论。 我不明白为什么memmove在MSVC上表现不同? 我在两个地方使用了memmove ,奇怪的是第一个工作正常。

任何帮助,将不胜感激。

尝试移动strlen(extension) + 1个字节,这样您不仅可以移动扩展字符,还可以移动尾随空字符。 例如,如果扩展名为“abc”,那么您只向前移动一个空格中的3个字符。 'c'字符后面可能有空字符,但之后没有空字符,因此当您移动字符时字符串将变为未终止状态。

你的第二个memmove写入终止'\\ 0'字节。 您可以移动strlen(extension)+1个字节来解决该问题。 我怀疑在GCC你很幸运,在下一个内存位置碰巧有一个额外的'\\ 0'字节。

很确定这与memmove无关,而是你的字符串逻辑的其余部分,这是一个混乱和非常低效。 为什么不只是识别字符串的3个部分及其相应的长度,而不是在开头复制,然后将它们复制到正确偏移处的目标缓冲区中?

或者,如果您只需要使用printf的结果,甚至不要复制! 只需确定长度并执行以下操作:

printf("Directory: %.*s\n", dir_len, full_pathname);
printf("Filename: %.s*\n", name_len, full_pathname+name_start);
printf("Extension: %.*s\n", ext_len, full_pathname+ext_start);

如果您使用snprintf格式化文本以在UI元素中显示,则同样有效...

memmove()时不包括空字符。 尝试这个:

        memmove(last_separator + 1, last_separator, strlen(last_separator)+1); 
        memmove(extension + 1, extension, strlen(extension)+1);*/

编辑:这是一个更好的方式,你正在做同样的事情。 这不涉及memmoves。 但是当然你需要单独的内存分配(我使用strdup())。 Null也在由strdup()分配的相同内存空间中处理。

    struct path_info* splitpath1(const char *full_path)
{
    char * path = strdup(full_path);
    char * fileWithExt = strtok((char *)strrchr(path,'\\'),"\\");

    struct path_info *p = (struct path_info*) malloc(sizeof(struct path_info));  /* Extra space for padding and shifting */
    p->filename = strtok(fileWithExt, ".");
    p->extension = strtok(NULL, ".");

    strtok((char *)strchr(path,'\\'),"\\");
    p->directory = path;

    return p;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM