C缓冲区溢出问题

4

我尝试编写一个函数,将文本 t 中所有出现的 str1 替换为 str2,但我一直收到“缓冲区溢出”错误消息。请问我的函数有什么问题?

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

//replace all *str1 in *t with *str2, put the result in *x, return *x
char * result(char *str1,char *str2,char *t)
{
    char *x=NULL,*p=t,*r=t;
    x=malloc(400*sizeof(char));
    assert(x!=NULL);
    x[0]='\0';
    r=strstr(t,str1); //r is at the first occurrence of str1 in t, p is at the beginning of t
    while(r!=NULL)
    {
        strncat(x,p,r-p); //copy r-p chars from p to x
        strcat(x,str2); //copy str2 to x
        p=r+strlen(str1); //p will be at the first char after the last occurrence of str1 in t
        r=strstr(r+strlen(str1),str1); //r goes to the next occurrence of str1 in t
    }
    strcat(x,p);
    return x;
}

我没有使用gets()函数来读取任何char数组。

我的编译器是gcc版本4.6.3


我更新了代码,它可以工作,但结果并不如预期。

main()函数:

int main(void)
{
    char *sir="ab",*sir2="xyz",*text="cabwnab4jkab",*final;
    final=result(sir,sir2,text);
    puts(final);
    free(final);
    return 0;
}

打印字符串:
b

我期望得到cxyzwnxyz4jkxyz


5
无法返回x,因为它是该函数的局部变量。 - eq-
1
请查看编辑中与您的结果以及strcatstrcpy之间的区别相关的内容。 - pb2q
通过调试器逐步执行此代码或每次循环打印变量的值,应该可以清楚地看出问题所在。 - bta
在C语言中,sizeof(char)的定义为1。虽然这只是一个小问题,但它暗示了你对该语言理解上存在更深层次的问题。 - mlp
2个回答

7

看起来你把strncpy的参数搞混了:第二个参数是源字符串,而不是要复制的字符数上限,应该是第三个参数:

 strncpy(x, p, r - p); // copy r - p chars from p to x

此外,您应该使用strcat而不是strcpy。使用strcpy,每次都会用替换字符串覆盖结果的内容。使用strcat,请确保在开始之前使用\0初始化结果。
最后,您正在从函数返回对局部变量x的引用:不能这样做,因为内存在函数返回后无法使用。

谢谢!我会尝试使用动态分配。 - Cristi

2
你的代码有一些奇怪的bug。
首先,x是指向你的目标缓冲区的指针。由于某种原因,你正在直接将所有内容复制到 x 中,也就是将所有内容复制到缓冲区的开头,从而覆盖了之前已经复制的数据。这完全没有任何意义。你为什么要这样做?你需要创建一个专门的指针,以保持当前目标位置在 x 中,并将数据写入该位置(而不是写入 x)。
我看到你编辑了你的代码,并用连接替换了复制。嗯……虽然这可能会解决问题,但这仍然是错误的设计。strcat / strncat 函数在好的 C 代码中不应出现。无论如何,你的代码仍然有问题,因为你尝试在未初始化的缓冲区 x 上使用 strcat 函数。你需要首先将 x 初始化为空字符串。
其次,你搜索替换字符串时还有一个更微妙的问题。在循环结束时,你继续从下一个符号开始搜索 r=strstr(r+1,str1),也就是只将搜索位置增加了 1。我不确定这是否是你想要的。
考虑输入文本为 aaaa,并请求将 aa 替换为 bc。在这种情况下,你希望进行多少次替换?aaaa 中有多少个 aa 出现?2 还是 3?如果你想得到 bcbc 作为结果(2 次替换),你必须将 r 增加 strlen(str1) 而不是增加 1。
事实上,在当前的实现中,你设置了 p=r+strlen(str1),但仍继续从位置 r+1 开始搜索。这将导致在搜索字符串重叠的情况下完全没有意义的结果,就像我的示例中一样。请尝试一下:
char *str1="aa",*str2="xyz",*text="aaaa",*final;
final=result(str1,str2,text);

看看会发生什么。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接