这里的stpncpy()有问题吗?

时间:2015-10-23 08:16:02

标签: c++ c

这是一个现有代码,它找到与父路径相对应的相对路径。它已经在平台上正常工作,除了SUSE 12和GCC 4.7。 我在评论中提到了错误输出之一。 我想了解为什么会发生这种情况? 此代码有什么问题? 子字符串和父字符串都以NUL字符结尾。我看到的唯一另一件事是源和目标从同一个内存位置传递,换句话说我们正在尝试更新相同内存位置的值。 这是真正的问题吗?

//child = /dev/shm/4/tmp/backup/datadir/performance_schema/events_stages_summary_by_account_by_event_name.frm 
//parent =  /dev/shm/4/tmp/backup

char* get_relative_path(char *child, const char *parent)
{
    char* start= child;
    static char dot[] = "." ;

    ....
    ....

    /* Check if child = parent + "/" + ....  */
    if (strstr(child, parent) == child)
    {
        int parent_len= strlen(parent);

        /* parent path may or may not have the "/" suffix. check for both. */
        if (parent[parent_len-1] == FN_LIBCHAR ||
            child[parent_len] == FN_LIBCHAR)
        {
            child+= parent_len;
            while (*child && *child == FN_LIBCHAR)
                child++;
            if (*child == 0)
                return dot;
        }
    }
   // At this point the value of 
   // start = /dev/shm/4/tmp/backup/datadir/performance_schema/events_stages_summary_by_account_by_event_name.frm 
   // child = datadir/performance_schema/events_stages_summary_by_account_by_event_name.frm

    if(start != child)
    {
        stpncpy(start, child, PATH_MAX);
    }

   // At this point  expected value of  start = datadir/performance_schema/events_stages_summary_by_account_by_event_name.frm
   // But actual value of start =  datadir/performance_schenamevents_stages_summary_by_account_by_event_name.frm 

   return start;
}

1 个答案:

答案 0 :(得分:5)

来自stpncpy的手册页:The strings may not overlap.

所以你应该使用memmove,否则行为是未定义的。

stpncpy(start, child, PATH_MAX);应该是 memmove(start, child, PATH_MAX > strlen(child) + 1? strlen(child) + 1: PATH_MAX);

您还应该记住,如果在大型数组上使用小字符串,stpncpy效率非常低,因为每次都会写n个字符。在你的情况下,它会在你的字符串后写出大约4000 '\0' Man Page说

  

在dest上写入了n个字符。       如果长度strlen(src)小于n,则为剩余字符       在dest指向的数组中填充空字节('\ 0')