这个问题出现在我正在处理的一个较大程序的模块中,这里是一个小模拟:
#include <iostream>
#include <vector>
using namespace std;
struct node{
int key;
vector<int> connections;
};
int main(void){
int size = 10;
node *A;
A=(node*)malloc((size)*sizeof(node));
int i;
for(i=0;i<size;i++){
A[i].key = i;
if(i%2 == 0) A[i].connections.push_back(i);
}
for(i=0;i<size;i++) {
if(A[i].connections.size() > 0) {
cout << A[i].key << "---" << A[i].connections.size() << endl;
}
}
free(A);
return 0;
}
这是我在运行 valgrind ./testCode
时得到的一小部分
==30433== Conditional jump or move depends on uninitialised value(s)
==30433== at 0x400F63: std::vector<int, std::allocator<int> >::push_back(int const&) (stl_vector.h:915)
==30433== by 0x400DF0: main (testCode.cpp:25)
根据我的理解,问题在于 vector 的 push_back
函数中有一个 if 语句使用了一些未初始化的值。我不确定到底是什么。玩了一下,发现问题出在我使用了malloc
。如果我使用 calloc
我根本不会收到任何警告。如果我使用 new
也是一样。然而,在所有情况下,程序的行为方式完全相同。这里发生了什么?即使收到所有这些警告,使用 malloc
是否安全?
最佳答案
不,这里使用malloc
是不安全的。
malloc
是分配内存的 C 方式。它不考虑 C++ 构造函数。
calloc
也是 C,但它会零初始化您的内存。这就是 std::vector
起作用的原因(然而,它也是未定义的行为,因为可能有一个 vector
实现需要初始化为非零的其他值)。
有很多方法可以解决这个问题:
改用
新节点
。如果您不能这样做,您至少可以在
malloc
返回的内存上做一个新的放置 (new (ptr) Node()
)。使用智能指针和
make_shared
或make_unique
。这样,您甚至不需要关心释放内存。最好的方法可能是使用
<std::vector
(如另一个答案中所建议的)或std::array
。
关于c++ - Valgrind 提示使用依赖于未初始化字节的条件跳转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41268913/