未初始化的价值和铿锵优化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了未初始化的价值和铿锵优化相关的知识,希望对你有一定的参考价值。

我创建了一个程序来打印“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
", _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
", _string);
}

还谢谢@Mat

答案

你有3个问题:

  • myString未初始化,因此调用strlen(myString)没有意义。在调用strlen之前,您需要将其设置为有意义的内容
  • 你的malloc调用是错误的,你不应该分配strlen(...) * sizeof(char),而是strlen(...) + 1,因为C中的字符串是空终止的,你必须为null终止符分配空间。此外,没有必要与sizeof(char)相乘,因为这保证等于1
  • 在malloc之后,您无法将指针指定给其他内容:myString = "Hello World!";。这就是Valgrind所抱怨的,它是一个内存泄漏。使用strcpy复制字符串,而不是使用=赋值。

此外,在程序结束时,free()所有内存都是一个好习惯。

以上是关于未初始化的价值和铿锵优化的主要内容,如果未能解决你的问题,请参考以下文章

铿锵声、openMP 和 CMake

片段未与片段管理器关联。 (对话片段)

铿锵声:错误:链接器命令失败,退出代码为 1(使用 -v 查看调用)而实现?

优化 C# 代码片段、ObservableCollection 和 AddRange

从底部工作表对话框片段中获取价值

铿锵声“你好,世界!” windows中的链接错误