在valgrind输出中混淆未初始化的值和条件跳转指示

时间:2014-11-18 12:45:36

标签: c++ initialization valgrind

通过valgrind运行SDL Linux多媒体应用程序,弹出的错误之一通常是基于未初始化值的条件跳转,但我无法在代码中查明问题。这看起来像是误报,但我对valgrind的输出感到困惑。

我的问题有两方面:1)我没有看到有条件的跳转,valgrind说它发生了,2)我没有看到有问题的分配在它所说的线上未初始化的价值来源。

以下是运行valgrind --track-origins=yes

时出现此错误的示例
126 ==10430== Conditional jump or move depends on uninitialised value(s)
127 ==10430==    at 0x60F9135: getenv (getenv.c:84)
128 ==10430==    by 0x6161485: tzset_internal (tzset.c:405)
129 ==10430==    by 0x6161648: __tz_convert (tzset.c:624)
130 ==10430==    by 0x406EC5: CLog::IIOCP_LogMessage(char const*, ...) (Log.cpp:80)
131 ==10430==    by 0x41453A: ConnectionThread::Connect() (ConnectionThread.cpp:224)
132 ==10430==    by 0x4149C5: ConnectionThread::DoRun() (ConnectionThread.cpp:318)
133 ==10430==    by 0x41499F: ConnectionThread::IOClientThread(void*) (ConnectionThread.cpp:313)
134 ==10430==    by 0x50D1B4F: start_thread (pthread_create.c:304)
135 ==10430==    by 0x619F7BC: clone (clone.S:112)
136 ==10430==  Uninitialised value was created by a stack allocation
137 ==10430==    at 0x4057D0: Video::DrawGraphic() (video.cpp:49)

这是DrawGraphics方法:

void Video::DrawGraphic(void)
{
    if (exp_timer)
    {   
        if (MainSur != NULL)
        {   
            SurBlit();
            exp_timer = false;
        }   
        else
        {   
            printf("\nError in DrawGraphic: MainSur is NULL.\n");
        }   
        FPS++;
        if (SDL_GetTicks() - TicksReadPipe >= 1000)
        {   
            ScrStrategy.OnReadPackets(connThread.GetPackets());
            TicksReadPipe = SDL_GetTicks();
        }   
    }   
    if (SDL_GetTicks() - CurrentTicks >= 1000)
    {   
        CurrentTicks = SDL_GetTicks();
        FPS = 0;   
    }   
}

所有变量都是Video类的成员,并在构造时分配。我在这里看不到任何堆栈分配。

这是getenv函数(我们没有输入折叠的if-branch)。我的glibc版本为2.13-38+deb7u6_all.deb,函数位于usr/src/glibc/eglibc-2.13/stdlib/getenv.c

33 char *
34 getenv (name)
35      const char *name;
36 {
37   size_t len = strlen (name);
38   char **ep;
39   uint16_t name_start;
40 
41   if (__environ == NULL || name[0] == '\0')
42     return NULL;
43 
44   if (name[1] == '\0')
45 +-- 25 lines: {-------------------------------------------------------------
70   else
71     {
72 #if _STRING_ARCH_unaligned
73       name_start = *(const uint16_t *) name;
74 #else
75       name_start = (((const unsigned char *) name)[0]
76             | (((const unsigned char *) name)[1] << 8));
77 #endif
78       len -= 2;
79       name += 2;
80 
81       for (ep = __environ; *ep != NULL; ++ep)
82     {
83 #if _STRING_ARCH_unaligned
84       uint16_t ep_start = *(uint16_t *) *ep;
85 #else
86       uint16_t ep_start = (((unsigned char *) *ep)[0]
87                    | (((unsigned char *) *ep)[1] << 8));
88 #endif
89 
90       if (name_start == ep_start && !strncmp (*ep + 2, name, len)
91           && (*ep)[len + 2] == '=')
92         return &(*ep)[len + 3];
93     }
94     }
95     
96   return NULL;
97 }

我没有在第84行看到有条件的跳跃。

getenv确实来自tzset_internal tzset.c:405tzset_internal本身来自__tz_convert tzset.c:624,所以我相信我查看的源与valgrind使用的调试符号相匹配。

我错过了什么,或者如果没有,为什么valgrind将我指向这些源行/块?

0 个答案:

没有答案