我在valgrind
内运行了我的C二进制文件的调试版本,它返回了许多排序Conditional jump or move depends on uninitialised value(s)
的错误。
使用符号表,valgrind
告诉我在我的程序中查找此问题的位置:
==23899== 11 errors in context 72 of 72:
==23899== Conditional jump or move depends on uninitialised value(s)
==23899== at 0x438BB0: _int_free (in /foo/bar/baz)
==23899== by 0x43CF75: free (in /foo/bar/baz)
==23899== by 0x4179E1: json_tokener_parse_ex (json_tokener.c:593)
==23899== by 0x418DC8: json_tokener_parse (json_tokener.c:108)
==23899== by 0x40122D: readJSONMetadataHeader (metadataHelpers.h:345)
==23899== by 0x4019CB: main (baz.c:90)
我有以下函数readJSONMetadataHeader(...)
来调用json_tokener_parse()
:
int readJSONMetadataHeader(...) {
char buffer[METADATA_MAX_SIZE];
json_object *metadataJSON;
int charCnt = 0;
...
/* fill up the `buffer` variable here; basically a */
/* stream of characters representing JSON data... */
...
/* terminate `buffer` */
buffer[charCnt - 1] = '\0';
...
metadataJSON = json_tokener_parse(buffer);
...
}
函数json_tokener_parse()
依次如下:
struct json_object* json_tokener_parse(const char *str)
{
struct json_tokener* tok;
struct json_object* obj;
tok = json_tokener_new();
obj = json_tokener_parse_ex(tok, str, -1);
if(tok->err != json_tokener_success)
obj = (struct json_object*)error_ptr(-tok->err);
json_tokener_free(tok);
return obj;
}
跟踪回readJSONMetadataHeader()
后,似乎未初始化的值是char []
(或const char *
)变量buffer
,它被输入json_tokener_parse()
,反过来被送到json_tokener_parse_ex()
。
但buffer
变量填充了数据,然后在调用json_tokener_parse()
函数之前终止。
那么为什么valgrind
说这个值未初始化?我错过了什么?
答案 0 :(得分:2)
我没有看到charCnt
已初始化。
要查看它是否来自buffer
,只需使用= {0}
初始化它,这也会使缓冲区的空终止过时。
答案 1 :(得分:2)
它从valgrind错误报告中看起来好像您的应用程序是静态链接的(特别是free
似乎在主可执行文件中,而不是libc.so.6
)。
Valgrind将报告静态链接应用程序的伪造错误。
更准确地说,libc中存在故意的“不关心”错误。当您动态链接应用程序时,默认情况下会禁止此类错误(通过Valgrind附带的抑制文件)。
但是当您静态链接您的应用程序时,Valgrind并不知道错误的代码来自libc.a,因此它会报告它们。
通常,在Linux上静态链接应用程序是一个坏主意(TM)。
在Valgrind下运行这样的应用程序:加倍:Valgrind将无法拦截malloc/free
调用,并且将有效地捕获仅未初始化的内存读取,并且不堆缓冲区溢出(或其他堆损坏错误),它通常很擅长。
答案 2 :(得分:1)
查看您未展示的json_tokener_parse_ex()
。它可能正试图释放一些未初始化的东西。
答案 3 :(得分:1)
buffer[charCnt - 1] = '\0';
如果charCnt恰好为零,至少会失败。