【问题标题】:Is something wrong with stpncpy() here?这里的 stpncpy() 有问题吗?
【发布时间】:2015-10-23 08:16:02
【问题描述】:

这是一个找到与父路径相对应的相对路径的现有代码。除了 SUSE 12 和 GCC 4.7 之外,它一直在平台上按预期工作。 我在 cmets 中提到了错误的输出之一。 我试图了解为什么会发生这种情况? 这段代码有什么问题? 子字符串和父字符串都以 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;
}

【问题讨论】:

  • stpncpy 的手册页说字符串可能重叠。您可以通过使用一个向后开始的函数来解决它,因此不会从已写入的位置读取。我不知道这是否是真正快速查看的实际问题,但这是一个潜在问题。
  • Ok ... jite 和@mch 指出了同样的问题

标签: c++ c


【解决方案1】:

来自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'
手册页说

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

【讨论】:

  • 上述代码多年来一直运行良好,但突然我们开始看到这个问题。嗯..但我看到你的观点可能似乎是手册页上提到的句子The string may not overlap的罪魁祸首。
  • 让我尝试一下您的解决方案,一旦可行,我会将其标记为答案。所以我的问题的实际答案是,如果内存重叠,使用 stpncpy()、strcpy()、strncpy() 是不安全的。
  • 在重叠的字符串上使用这个函数可能会导致未定义的行为——包括“按预期工作”以及“...除了这里”。是否有效取决于功能的实现;对于不同的编译器和/或平台,库的实现可能会有所不同。
猜你喜欢
  • 2011-08-04
  • 2023-04-10
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-03
  • 1970-01-01
相关资源
最近更新 更多