修改传递给函数C的char数组

时间:2019-06-03 18:18:17

标签: c arrays char segmentation-fault strcat

我想在一个函数内连接2个字符串。但是,我希望该函数还修改目标字符串(char数组)。

到目前为止,我在下面获得了这段代码,但是它显示了“分段错误”,我不知道该如何解决。谢谢。

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

char *my_strcat(char *dest, const char * src) {
    char *tab = (char*) malloc(sizeof(char) * (strlen(*dest) + strlen(src) + 1));
    if(NULL == tab)
        return NULL;
    strcpy(tab, dest);
    strcpy(tab, src);
    free(dest);
    dest = (char*)malloc(sizeof(char) * (strlen(tab)+1));
    strcpy(dest, tab);
    return tab; }

int main(int argc, char **argv) {
    char *dst = NULL, *src = NULL, *r = NULL;
    int i;
    src = malloc(sizeof(char) * 100);
    strcpy(src, "fifty");

    dst = malloc (sizeof (char *) * 100);
    strcpy(src, "four");

    r = my_strcat(dst, src);
    printf("%s\n", r);
    printf("%s\n", dst);

    free(r);
    free(dst);
    free(src);

    return 0; }

2 个答案:

答案 0 :(得分:1)

您的代码中有几个问题。您可以使用valgrindclang-tidy之类的工具来帮助您。

这是您的具有行号的代码

 1  /* -*- compile-command: "gcc prog.c; ./a.out"; -*- */
 2  #include <stdio.h>
 3  #include <stdlib.h>
 4  #include <string.h>
 5  
 6  char *my_strcat(char *dest, const char *src)
 7  {
 8    char *tab = (char *)malloc(sizeof(char) * (strlen(*dest) + strlen(src) + 1));
 9    if (NULL == tab)
10      return NULL;
11    strcpy(tab, dest);
12    strcpy(tab, src);
13    free(dest);
14    dest = (char *)malloc(sizeof(char) * (strlen(tab) + 1));
15    strcpy(dest, tab);
16    return tab;
17  }
18  
19  int main(int argc, char **argv)
20  {
21    char *dst = NULL, *src = NULL, *r = NULL;
22    int i;
23    src = malloc(sizeof(char) * 100);
24    strcpy(src, "fifty");
25  
26    dst = malloc(sizeof(char *) * 100);
27    strcpy(src, "four");
28  
29    r = my_strcat(dst, src);
30    printf("%s\n", r);
31    printf("%s\n", dst);
32  
33    free(r);
34    free(dst);
35    free(src);
36  
37    return 0;
38  }

让我们使用cland-tidy进行静态分析:

clang-tidy-7 prog.c --

打印一堆消息:

8 warnings generated.
/home/picaud/Temp/prog.c:8:46: warning: 1st function call argument is an uninitialized value [clang-analyzer-core.CallAndMessage]
  char *tab = (char *)malloc(sizeof(char) * (strlen(*dest) + strlen(src) + 1));
                                             ^
/home/picaud/Temp/prog.c:26:9: note: Storing uninitialized value
  dst = malloc(sizeof(char *) * 100);
        ^
/home/picaud/Temp/prog.c:29:7: note: Calling 'my_strcat'
  r = my_strcat(dst, src);
      ^
/home/picaud/Temp/prog.c:8:46: note: 1st function call argument is an uninitialized value
  char *tab = (char *)malloc(sizeof(char) * (strlen(*dest) + strlen(src) + 1));
                                             ^
/home/picaud/Temp/prog.c:8:53: warning: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *';
     

等...

第一行说明dest未初始化,您可以将其追溯到:

26    dst = malloc(sizeof(char *) * 100);
27    strcpy(src, "four");

这肯定是一个错误,必须替换为

26    dst = malloc(sizeof(char *) * 100);
27    strcpy(dst, "four");

现在您可以重新运行clang-tidy。第一条消息是:

/home/picaud/Temp/prog.c:8:53: warning: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *';
remove * [clang-diagnostic-int-conversion]
  char *tab = (char *)malloc(sizeof(char) * (strlen(*dest) + strlen(src) + 1));             
                                                    ^~~~~

立即指出另一个错误,请替换:

8     char *tab = (char *)malloc(sizeof(char) * (strlen(*dest) + strlen(src) + 1));

作者

8     char *tab = (char *)malloc(sizeof(char) * (strlen(dest) + strlen(src) + 1));

您也有

/home/picaud/Temp/prog.c:26:9: warning: Result of 'malloc' is converted to a pointer of type 'char', which is incompatible with sizeof operand type 'char *' [clang-analyzer-unix.MallocSizeof]
  dst = malloc(sizeof(char *) * 100);
        ^

因此您必须更换:

  dst = malloc(sizeof(char *) * 100);

通过

  dst = malloc(sizeof(char) * 100);

重新运行clang-tidy仍然显示一些问题:

 /home/picaud/Temp/prog.c:27:3: note: Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
/home/picaud/Temp/prog.c:31:3: warning: Use of memory after it is freed [clang-analyzer-unix.Malloc]
  printf("%s\n", dst);
  ^
/home/picaud/Temp/prog.c:26:9: note: Memory is allocated
  dst = malloc(sizeof(char) * 100);
        ^
/home/picaud/Temp/prog.c:29:7: note: Calling 'my_strcat'
  r = my_strcat(dst, src);
      ^
/home/picaud/Temp/prog.c:9:3: note: Taking false branch
  if (NULL == tab)
  ^
/home/picaud/Temp/prog.c:13:3: note: Memory is released
  free(dest);
  ^
/home/picaud/Temp/prog.c:29:7: note: Returning; memory was released via 1st parameter
  r = my_strcat(dst, src);
      ^
/home/picaud/Temp/prog.c:31:3: note: Use of memory after it is freed
  printf("%s\n", dst);

我让你检查所有这一切。在这些警告之后,我将为您的代码提供此新版本:

/* -*- compile-command: "gcc prog.c; ./a.out"; -*- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *my_strcat(char *dest, const char *src)
{
  char *tab = (char *)malloc(sizeof(char) * (strlen(dest) + strlen(src) + 1));
  if (NULL == tab)
    return NULL;
  strcpy(tab, dest);
  strcpy(tab+strlen(dest), src);
  return tab;
}

int main(int argc, char **argv)
{
  char *dst = NULL, *src = NULL, *r = NULL;
  int i;
  src = malloc(sizeof(char) * 100);
  strcpy(src, "fifty");

  dst = malloc(sizeof(char) * 100);
  strcpy(dst, "four");

  r = my_strcat(dst, src);
  printf("%s\n", r);
  printf("%s\n", dst);

  free(r);
  free(dst);
  free(src);

  return 0;
}

运行时,此代码将打印:

gcc prog.c; ./a.out
fourfifty
four

您可以使用valgrind来检查是否没有内存泄漏:

valgrind ./a.out 
==4023== Memcheck, a memory error detector
==4023== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4023== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==4023== Command: ./a.out
==4023== 
fourfifty
four
==4023== 
==4023== HEAP SUMMARY:
==4023==     in use at exit: 0 bytes in 0 blocks
==4023==   total heap usage: 4 allocs, 4 frees, 1,234 bytes allocated
==4023== 
==4023== All heap blocks were freed -- no leaks are possible
==4023== 
==4023== For counts of detected and suppressed errors, rerun with: -v
==4023== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

好学!

答案 1 :(得分:1)

dstmain中分配。要在函数中修改该分配,可以返回新指针或将指针传递给指针。由于返回了另一个指针,因此必须将指针传递给指针char **dest,并在函数中进行一些更改以适应该更改。

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

char *my_strcat ( char **dest, const char * src) {
    char *tab = malloc ( sizeof ( char) * (strlen ( *dest) + strlen ( src) + 1));//dereference dest
    if ( NULL == tab)
        return NULL;
    strcpy ( tab, *dest);//dereference dst
    strcat ( tab, src);
    free ( *dest);//dereference dest
    *dest = malloc ( sizeof ( char) * ( strlen ( tab) + 1));//dereference dest
    strcpy ( *dest, tab);//dereference dest
    return tab;
}

int main(int argc, char **argv) {
    char *dst = NULL, *src = NULL, *r = NULL;
    src = malloc ( sizeof ( char) * 100);
    strcpy ( src, "fifty");

    dst = malloc ( sizeof ( char) * 100);
    strcpy ( dst, "four");

    r = my_strcat ( &dst, src);//use address of dst
    printf ( "%s\n", r);
    printf ( "%s\n", dst);

    free ( r);
    free ( dst);
    free ( src);

    return 0;
}