您的代码中有几个问题。您可以使用valgrind、clang-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)
好好学习!