为什么 strcpy 将垃圾字符附加到一小部分字符串的末尾?

Why is strcpy appending junk characters to the end of a small fraction of strings?

我有一个函数将包含 hyperlink 的字符串作为其输入并尝试输出相同的 hyperlink 除非它包含问号,该字符和任何它后面的字符被清除。

首先,我打开一个文本文件并读入包含 link 且仅包含 link 的行,如下所示:

FILE * ifp = fopen(raw_links,"r");
char link_to_filter[200];

if(ifp == NULL)
{
    printf("Could not open %s for writing\n", raw_links);
    exit(0);
}

while(fscanf(ifp,"%s", link_to_filter) == 1)
{
    add_link(a,link_to_filter, link_under_wget);
}; 

fclose(ifp);

add_link 所做的部分工作是在问号后删除 link 中不必要的部分(如 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/online-giving/step1.php?new=1)导致我对 wget 的调用出现问题。它通过此函数 remove_extra 馈送 link_to_filter 来完成此操作,如下所示。

char * remove_extra(char * url)
{
    char * test = url;
    int total_size;

    test = strchr(url,'?');

    if (test != NULL)
    {
        total_size = test-url;
        url[total_size] = '[=11=]';
    }

    return url;
}

在 remove_extra 的末尾,从 remove_extra 返回后,在使用 strcpy 之前立即调用 printf,就像这样

printf("%s",url);

将打印出我期望看到的内容(例如 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/online-giving/step1.php 不带“?”或尾随字符),但在此代码块运行后立即

struct node * temp = (struct node *)malloc(sizeof(struct node));
char * new_link = remove_extra(url);
temp->hyperlink =(char *)malloc(strlen(new_link) * sizeof(char));
strncpy(temp->hyperlink, new_link, strlen(new_link));

成员 hyperlink 上的 printf 的结果偶尔在末尾有一个垃圾字符(有时 'A' 或 'Q' 或 '!',但始终相同对应于同一字符串的字符)。如果每个 link 或特定类型的 link 都发生这种情况,我可以想出办法, 但它可能每 20 次 link 发生一次,并且它恰好发生在 link 短和长。

例如 xxxxxxxxxxxxxxxxxxxx/hr/ --> xxxxxxxxxxxxxxxxxxxx/hr/!

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/windows-to-the-past/ --> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/windows-to-the-past/Q

strcpy 和自制字符串复制循环都会发生这种情况,所以我倾向于认为这不是 strcpy 的错,但我想不出错误还会出在哪里。

很可能您忘记在字符串末尾复制一个空终止符,请记住 strlen(str) 给出了可见字符的数量,您还需要在末尾添加“\0”。 你需要做

temp->hyperlink =(char *)malloc(strlen(new_link)+1);//char is one byte, sizeof(char)=1

strcpy(temp->hyperlink, new_link); 应该可以正常工作。

为什么不使用 strdup

如果您将 len 计算为 src 的长度,那么 strncpy 的天真用法——尽管它可能很诱人——是不正确的:

 size_t len = strlen(src);
 dest = malloc(len);       /* DON'T DO THIS */
 strncpy(dest, src, len);  /* DON'T DO THIS, EITHER */

strncpy 正好复制 len 个字节;它确实 not 保证在末尾放置一个 NUL 字节。由于 len 恰好是 src 的长度,因此 src 的前 len 字节中没有 NUL 字节,并且不会插入 NUL 字节strncpy.

如果您使用 strcpy 代替(应该是 "unsafe" 接口):

strcpy(dest, src);

本来还可以,只是dest不够大。你真正需要做的是:

dest = malloc(strlen(src) + 1);  /* Note: include space for the NUL */
strcpy(dest, src);

或者,如果您有有用的 strdup 功能:

dest = strdup(src);