c语言 - 瓦尔格林德给出"Conditional jump or move depends on uninitialised value(s)"误差



我正在努力理解和解决">条件跳转或移动取决于未初始化的值"错误瓦尔格林德点,到目前为止没有成功。

我尝试初始化代码中的几乎所有内容(结构的数据元素除外(,即使很明显没有必要。我尝试调试并检查每个stack_t对象的所有成员是否已初始化并具有值。一切都无济于事 - valgrind 不断得出结论,由于未初始化的值而存在内存错误。

有趣的是,除了valgrind问题之外,所有测试都是完美无缺的。我一直在缩小代码的范围,直到我找到 valgrind 不喜欢的特定代码段。

下面是。这是来自文件堆栈.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;
}

据了解,一切看起来都很好。 但是瓦尔格林德给出了这个错误:

==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)

我将不胜感激任何可能阐明该主题的帮助或想法。

更新:正如凯文和卡米尔库克正确指出的那样,问题在于结构stack_t的_data成员未初始化,因此memcpy和memcmp实际上正在使用未初始化的内存,正如valgrind正确检测到的那样。

尽管通过句柄char*读取未初始化的内存不是未定义的行为(也不是通过memcpymemcmp函数(,但始终在读取之前初始化内存仍然被认为是一种很好的做法。

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

相关内容

最新更新