我创建了一个程序来将“ Hello World”字符串打印为波纹管:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void callString(char *_string);
int main()
{
char *myString;
// Allocating memory
myString = (char *)malloc(
(unsigned long)strlen(myString)
* sizeof(char)
);
myString = "Hello World!";
callString(myString);
// should I free(myString) here?
return 0;
}
static void
callString(char *_string)
{
printf("%s\n", _string);
}
编译和运行报告:
$ clang -Wall -Weverything -g hello.c -o hello
$ ./hello
Hello World!
看起来不错,但是,如果我尝试使用Valgrind分析内存,则会得到:
$ valgrind \
--track-origins=yes \
--leak-check=full \
--leak-resolution=high \
--num-callers=50 \
./hello
==31692== Memcheck, a memory error detector
==31692== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31692== Using Valgrind-3.14.0.GIT and LibVEX; rerun with -h for copyright info
==31692== Command: ./hello
==31692==
==31692== Use of uninitialised value of size 8
==31692== at 0x483ACC2: __strlen_sse2 (vg_replace_strmem.c:462)
==31692== by 0x109177: main (hello.c:9)
==31692== Uninitialised value was created by a stack allocation
==31692== at 0x109160: main (hello.c:7)
==31692==
==31692== Use of uninitialised value of size 8
==31692== at 0x483ACD4: __strlen_sse2 (vg_replace_strmem.c:462)
==31692== by 0x109177: main (hello.c:9)
==31692== Uninitialised value was created by a stack allocation
==31692== at 0x109160: main (hello.c:7)
==31692==
Hello World!
==31692==
==31692== HEAP SUMMARY:
==31692== in use at exit: 1 bytes in 1 blocks
==31692== total heap usage: 2 allocs, 1 frees, 1,025 bytes allocated
==31692==
==31692== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==31692== at 0x483777F: malloc (vg_replace_malloc.c:299)
==31692== by 0x109183: main (hello.c:9)
==31692==
==31692== LEAK SUMMARY:
==31692== definitely lost: 1 bytes in 1 blocks
==31692== indirectly lost: 0 bytes in 0 blocks
==31692== possibly lost: 0 bytes in 0 blocks
==31692== still reachable: 0 bytes in 0 blocks
==31692== suppressed: 0 bytes in 0 blocks
==31692==
==31692== For counts of detected and suppressed errors, rerun with: -v
==31692== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
如果使用-O3级别的优化标志进行编译,则会得到绿色信号。
$ valgrind \
--track-origins=yes \
--leak-check=full \
--leak-resolution=high \
--num-callers=50 \
./hello
==32000== Memcheck, a memory error detector
==32000== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==32000== Using Valgrind-3.14.0.GIT and LibVEX; rerun with -h for copyright info
==32000== Command: ./hello
==32000==
Hello World!
==32000==
==32000== HEAP SUMMARY:
==32000== in use at exit: 0 bytes in 0 blocks
==32000== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==32000==
==32000== All heap blocks were freed -- no leaks are possible
==32000==
==32000== For counts of detected and suppressed errors, rerun with: -v
==32000== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
优化似乎可以解决此处的一些内存问题。代码段有什么问题?哪一个被称为“使用未初始化的值”? myString?我该如何初始化?
编辑:正如@Lundin所建议的,我吸取了教训,不要直接用=分配字符串。谢谢。固定代码部分=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void callString(char *_string);
int main()
{
char *myString;
myString = (char *)malloc(
(unsigned long)strlen(myString)+1 * sizeof(char)
);
strncpy(myString, "Hello World", 11);
callString(myString);
free(myString);
return 0;
}
static void
callString(char *_string)
{
printf("%s\n", _string);
}
也感谢@Mat
答案 0 :(得分:1)
您有3个问题:
myString
未初始化,因此调用strlen(myString)
没有任何意义。您需要先将其设置为有意义的值,然后再调用strlen
您的malloc调用是错误的,您不应分配strlen(...) * sizeof(char)
,而应分配strlen(...) + 1
,因为C中的字符串以null终止,并且必须为null终止符分配空间。另外,也不必与sizeof(char)
相乘,因为保证等于1
。
在分配malloc之后,无法将指针分配给其他内容:myString = "Hello World!";
。这是Valgrind抱怨的,这是内存泄漏。字符串是使用strcpy
复制的,而不是使用=
分配的。
此外,最好在程序末尾free()
使用所有内存。