strcpy 和 strcat 的垃圾

Garbage with strcpy and strcat

我在 linux 做一个客户端-服务器项目,我需要连接一些字符串。

我在 windows 中的 visual studio 上尝试了我的代码,它工作正常,但 linux 它给了我一些垃圾。我有这个功能:

char* concat(char s1[], char s2[])
{
    int tam = 0;
    tam = strlen(s1);
    tam += strlen(s2);
    char *resultado =  malloc(sizeof(char) * tam) ;
    strcpy(resultado, s1); 
    strcat(resultado, s2); 
    return resultado;
}

我了解到问题是缺少 '[=12=]',我已经做到了:

 char* concat(char s1[], char s2[])
{
    int tam = 0;
    tam = strlen(s1);
    tam += strlen(s2);
    char *resultado =  malloc(sizeof(char) * tam) ;
    resultado[tam+1] = '[=11=]';
    strcpy(resultado, s1); 
    strcat(resultado, s2); 
    return resultado;
}

我调用该函数的前 4 次它起作用(垃圾消失了),但随后它给了我 `malloc():内存损坏

谁能帮帮我?

您没有为 nul 终止符分配 space,这是一个很常见的错误。

建议:

  1. 不要使用 sizeof(char) 根据定义它是 1。
  2. 检查 malloc() 没有 return NULL
  3. 永远记住nul字节。

所以你的代码会像这样固定

char *resultado =  malloc(1 + tam);
if (resultado == NULL)
    pleaseDoNotUse_resultado();

另外,请注意这一行

resultado[tam + 1] = '[=11=]';

有多个问题

  1. tam + 1 我们在分配的块之外。
  2. 你不需要这样做,strcpy()会为你做。

在这种情况下使用strcat()strcpy()是低效的,因为你已经知道要复制多少字节了,这个

char *concat(char *s1, char *s2)
{
    size_t l1;
    size_t l2;
    char  *resultado

    if ((s1 == NULL) || (s2 == NULL))
        return NULL;
    l1 = strlen(s1);
    l2 = strlen(s2);
    resultado =  malloc(1 + l1 + l2) ;
    if (resultado == NULL)
        return NULL;
    memcpy(resultado     , s1, l1); 
    memcpy(resultado + l1, s2, l2); 

    resultado[l1 + l2] = '[=12=]';
    return resultado;
}

会更有效率,即使当你像偏执狂一样检查 NULL 时,它也会比 strcpy()strcat() 更快,因为你只会计算长度一次。

您没有分配内存来保存终止的 null。请记住,strlen() 在计算字符串长度时不计算空终止符。不过,您需要在目标缓冲区中使用 space 来放置空终止符。

你应该写

 char *resultado =  malloc(tam + 1) ;

此外,

 resultado[tam+1] = '[=11=]';

是非常错误的,因为数组索引是基于 C 的 0 并且在这里,您正在超出分配的内存(是的,即使分配的大小也是 tam+1)这将调用 undefined behaviour。你根本不需要它,你可以摆脱它。

之后,作为旁注,正如 Iharob 所提到的,

  1. 在使用返回的指针之前检查 malloc() 是否成功。
  2. 在C标准中,sizeof(char)保证是1。在计算 malloc().
  3. 的大小时不需要使用它

您应该比结果字符串的长度多分配一个字节:

char *resultado =  malloc(tam + 1) ;

函数strcpystrcat负责终止NUL,您不必手动添加它。