Valgrind 给出 "Conditional jump or move depends on uninitialised value(s)" 错误
Valgrind gives "Conditional jump or move depends on uninitialised value(s)" error
我正在努力理解和解决“条件跳转或移动取决于未初始化的值”错误 valgrind 点,到目前为止没有成功。
我尝试初始化代码中的几乎所有内容(结构的数据元素除外),即使很明显没有必要。我尝试调试并检查每个 stack_t-object 的所有成员是否已初始化并具有值。一切都无济于事 - valgrind 不断得出结论,由于 未初始化的值 .
存在内存错误
有趣的是所有测试都完美无缺,除了 valgrind 问题。我一直在缩小代码的范围,直到找到 valgrind 不喜欢的特定代码片段。
在下面。这来自文件 stack.c:
#define GET_STACK_SIZE(x, y) (offsetof(stack_t, _data) + x * y)
typedef struct stack
{
size_t _capacity;
size_t _element_size;
size_t _top_of_stack;
char _data[1];
} stack_t;
stack_t *StackCreate(size_t capacity, size_t element_size)
{
stack_t *new_st = NULL;
assert(element_size > 0);
assert(capacity > 0);
new_st = malloc(GET_STACK_SIZE(capacity, element_size));
if (NULL == new_st)
{
return NULL;
}
new_st->_capacity = capacity;
new_st->_element_size = element_size;
new_st->_top_of_stack = 0;
return new_st;
}
stack_t *StackCopy(const stack_t *other)
{
stack_t *new_st;
assert(NULL != other);
new_st = StackCreate(other->_capacity, other->_element_size);
if (NULL == new_st)
return NULL;
memcpy(new_st, other, GET_STACK_SIZE(other->_capacity, other->_element_size));
new_st->_capacity = other->_capacity;
new_st->_element_size = other->_element_size;
new_st->_top_of_stack = other->_top_of_stack;
return new_st;
}
int StackEquals(const stack_t *st1, const stack_t *st2)
{
return memcmp(st1, st2,
GET_STACK_SIZE(st1->_capacity, st1->_element_size)) == 0;
}
这是我的测试文件:
#define NUM_OF_STACKS_IN_TEST (2)
#define CAPACITY_MULT (5)
stack_t *stacks[NUM_OF_STACKS_IN_TEST] = {NULL};
int init()
{
int i = 0;
for (; i < NUM_OF_STACKS_IN_TEST; ++i)
{
switch (i)
{
case 0:
stacks[i] = StackCreate((i + 1) * CAPACITY_MULT, sizeof(char));
if (NULL == stacks[i])
return EXIT_FAILURE;
break;
case 1:
stacks[i] = StackCopy(stacks[0]);
if (NULL == stacks[i])
return EXIT_FAILURE;
default:
break;
}
}
return EXIT_SUCCESS;
}
int StackCreateTest(void)
{
size_t i;
for (i = 0; i<NUM_OF_STACKS_IN_TEST>> 1; ++i)
{
if (StackEquals(stacks[i], stacks[i + 1]) != 1)
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int main(void)
{
if (EXIT_SUCCESS != init())
{
puts("initialization failed");
}
RUN_TEST(StackCreateTest); /* just a macro that runs StackCreateTest function */
end(); /* frees memory allocation */
return EXIT_SUCCESS;
}
据我所知,一切正常。但是 valgrind 给出了这个错误:
==25611== Conditional jump or move depends on uninitialised value(s)
==25611== at 0x4C35E6F: bcmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25611== by 0x108C4F: StackEquals (stack.c:92)
==25611== by 0x108D19: StackCreateTest (stack_test.c:113)
==25611== by 0x108C83: main (stack_test.c:72)
==25611== Uninitialised value was created by a heap allocation
==25611== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25611== by 0x108A62: StackCreate (stack.c:46)
==25611== by 0x108D79: init (stack_test.c:175)
==25611== by 0x108C67: main (stack_test.c:67)
==25611==
==25611== Conditional jump or move depends on uninitialised value(s)
==25611== at 0x4C35E91: bcmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25611== by 0x108C4F: StackEquals (stack.c:92)
==25611== by 0x108D19: StackCreateTest (stack_test.c:113)
==25611== by 0x108C83: main (stack_test.c:72)
==25611== Uninitialised value was created by a heap allocation
==25611== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25611== by 0x108A62: StackCreate (stack.c:46)
==25611== by 0x108D79: init (stack_test.c:175)
==25611== by 0x108C67: main (stack_test.c:67)
==25611==
==25611== Conditional jump or move depends on uninitialised value(s)
==25611== at 0x108D1D: StackCreateTest (stack_test.c:113)
==25611== by 0x108C83: main (stack_test.c:72)
==25611== Uninitialised value was created by a heap allocation
==25611== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25611== by 0x108A62: StackCreate (stack.c:46)
==25611== by 0x108D79: init (stack_test.c:175)
==25611== by 0x108C67: main (stack_test.c:67)
==25611==
StackCreateTest is OK!
==25611==
==25611== HEAP SUMMARY:
==25611== in use at exit: 0 bytes in 0 blocks
==25611== total heap usage: 3 allocs, 3 frees, 1,082 bytes allocated
==25611==
==25611== All heap blocks were freed -- no leaks are possible
==25611==
==25611== For counts of detected and suppressed errors, rerun with: -v
==25611== ERROR SUMMARY: 6 errors from 3 contexts (suppressed: 0 from 0)
如果有任何帮助或想法可以阐明该主题,我将不胜感激。
更新:
正如 kevin 和 KamilCuk 正确指出的那样,问题是结构 stack_t 的 _data 成员未初始化,因此 memcpy 和 memcmp 实际上使用的是未初始化的内存,因为 valgrind 正确检测到
虽然reading uninitialized memory through char*
handle is not undefined behavior (and isn't via memcpy
and memcmp
functions), still it is considered good practice to always initialize memory before reading.
Valgrind 正确诊断了“问题”,您 new_st = malloc(GET_STACK_SIZE(capacity, element_size));
分配了内存并且没有初始化 ( offsetof(stack_t, _data), offsetof(stack_t, _data) + x * y ]
范围内的内存。然后代码在 memcpy(new_st, other, GET_STACK_SIZE(other->_capacity, other->_element_size));
中读取它并在 memcmp(st1, st2,
中进行比较 - 因此 valgrind 显示未初始化的字节错误。
解决方法很简单 - 初始化内存。使用 calloc
或像 memset(new_st.data, 0, x * y)
.
这样调用 memset
我正在努力理解和解决“条件跳转或移动取决于未初始化的值”错误 valgrind 点,到目前为止没有成功。
我尝试初始化代码中的几乎所有内容(结构的数据元素除外),即使很明显没有必要。我尝试调试并检查每个 stack_t-object 的所有成员是否已初始化并具有值。一切都无济于事 - valgrind 不断得出结论,由于 未初始化的值 .
存在内存错误有趣的是所有测试都完美无缺,除了 valgrind 问题。我一直在缩小代码的范围,直到找到 valgrind 不喜欢的特定代码片段。
在下面。这来自文件 stack.c:
#define GET_STACK_SIZE(x, y) (offsetof(stack_t, _data) + x * y)
typedef struct stack
{
size_t _capacity;
size_t _element_size;
size_t _top_of_stack;
char _data[1];
} stack_t;
stack_t *StackCreate(size_t capacity, size_t element_size)
{
stack_t *new_st = NULL;
assert(element_size > 0);
assert(capacity > 0);
new_st = malloc(GET_STACK_SIZE(capacity, element_size));
if (NULL == new_st)
{
return NULL;
}
new_st->_capacity = capacity;
new_st->_element_size = element_size;
new_st->_top_of_stack = 0;
return new_st;
}
stack_t *StackCopy(const stack_t *other)
{
stack_t *new_st;
assert(NULL != other);
new_st = StackCreate(other->_capacity, other->_element_size);
if (NULL == new_st)
return NULL;
memcpy(new_st, other, GET_STACK_SIZE(other->_capacity, other->_element_size));
new_st->_capacity = other->_capacity;
new_st->_element_size = other->_element_size;
new_st->_top_of_stack = other->_top_of_stack;
return new_st;
}
int StackEquals(const stack_t *st1, const stack_t *st2)
{
return memcmp(st1, st2,
GET_STACK_SIZE(st1->_capacity, st1->_element_size)) == 0;
}
这是我的测试文件:
#define NUM_OF_STACKS_IN_TEST (2)
#define CAPACITY_MULT (5)
stack_t *stacks[NUM_OF_STACKS_IN_TEST] = {NULL};
int init()
{
int i = 0;
for (; i < NUM_OF_STACKS_IN_TEST; ++i)
{
switch (i)
{
case 0:
stacks[i] = StackCreate((i + 1) * CAPACITY_MULT, sizeof(char));
if (NULL == stacks[i])
return EXIT_FAILURE;
break;
case 1:
stacks[i] = StackCopy(stacks[0]);
if (NULL == stacks[i])
return EXIT_FAILURE;
default:
break;
}
}
return EXIT_SUCCESS;
}
int StackCreateTest(void)
{
size_t i;
for (i = 0; i<NUM_OF_STACKS_IN_TEST>> 1; ++i)
{
if (StackEquals(stacks[i], stacks[i + 1]) != 1)
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int main(void)
{
if (EXIT_SUCCESS != init())
{
puts("initialization failed");
}
RUN_TEST(StackCreateTest); /* just a macro that runs StackCreateTest function */
end(); /* frees memory allocation */
return EXIT_SUCCESS;
}
据我所知,一切正常。但是 valgrind 给出了这个错误:
==25611== Conditional jump or move depends on uninitialised value(s)
==25611== at 0x4C35E6F: bcmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25611== by 0x108C4F: StackEquals (stack.c:92)
==25611== by 0x108D19: StackCreateTest (stack_test.c:113)
==25611== by 0x108C83: main (stack_test.c:72)
==25611== Uninitialised value was created by a heap allocation
==25611== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25611== by 0x108A62: StackCreate (stack.c:46)
==25611== by 0x108D79: init (stack_test.c:175)
==25611== by 0x108C67: main (stack_test.c:67)
==25611==
==25611== Conditional jump or move depends on uninitialised value(s)
==25611== at 0x4C35E91: bcmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25611== by 0x108C4F: StackEquals (stack.c:92)
==25611== by 0x108D19: StackCreateTest (stack_test.c:113)
==25611== by 0x108C83: main (stack_test.c:72)
==25611== Uninitialised value was created by a heap allocation
==25611== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25611== by 0x108A62: StackCreate (stack.c:46)
==25611== by 0x108D79: init (stack_test.c:175)
==25611== by 0x108C67: main (stack_test.c:67)
==25611==
==25611== Conditional jump or move depends on uninitialised value(s)
==25611== at 0x108D1D: StackCreateTest (stack_test.c:113)
==25611== by 0x108C83: main (stack_test.c:72)
==25611== Uninitialised value was created by a heap allocation
==25611== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25611== by 0x108A62: StackCreate (stack.c:46)
==25611== by 0x108D79: init (stack_test.c:175)
==25611== by 0x108C67: main (stack_test.c:67)
==25611==
StackCreateTest is OK!
==25611==
==25611== HEAP SUMMARY:
==25611== in use at exit: 0 bytes in 0 blocks
==25611== total heap usage: 3 allocs, 3 frees, 1,082 bytes allocated
==25611==
==25611== All heap blocks were freed -- no leaks are possible
==25611==
==25611== For counts of detected and suppressed errors, rerun with: -v
==25611== ERROR SUMMARY: 6 errors from 3 contexts (suppressed: 0 from 0)
如果有任何帮助或想法可以阐明该主题,我将不胜感激。
更新: 正如 kevin 和 KamilCuk 正确指出的那样,问题是结构 stack_t 的 _data 成员未初始化,因此 memcpy 和 memcmp 实际上使用的是未初始化的内存,因为 valgrind 正确检测到
虽然reading uninitialized memory through char*
handle is not undefined behavior (and isn't via memcpy
and memcmp
functions), still it is considered good practice to always initialize memory before reading.
Valgrind 正确诊断了“问题”,您 new_st = malloc(GET_STACK_SIZE(capacity, element_size));
分配了内存并且没有初始化 ( offsetof(stack_t, _data), offsetof(stack_t, _data) + x * y ]
范围内的内存。然后代码在 memcpy(new_st, other, GET_STACK_SIZE(other->_capacity, other->_element_size));
中读取它并在 memcmp(st1, st2,
中进行比较 - 因此 valgrind 显示未初始化的字节错误。
解决方法很简单 - 初始化内存。使用 calloc
或像 memset(new_st.data, 0, x * y)
.
memset