Valgrind抱怨使用有条件跳跃,这些跳跃取决于非初始化的字节



我有这个问题出现在我正在处理的较大程序的模块中,这是一个小模拟:

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

从我的理解中,问题是,在矢量的push_back函数内有一个IF语句,它使用了某些非传统的值。我不确定到底是什么。玩耍后,事实证明我使用malloc。如果我使用calloc,我根本不会收到任何警告。如果我使用new,也是如此。但是,在所有情况下,该程序的行为完全相同。这里发生了什么?即使我收到所有这些警告,也可以安全使用malloc吗?

不,在这里使用malloc是不安全的。

malloc是分配内存的C方式。它不考虑C 构造函数。

calloc也是C,但它使您的内存零零。这就是std::vector工作的原因(但是,这也是未定义的行为,因为可能有一个vector实现,需要将其初始化为零以外的其他功能)。

有很多方法可以解决这个问题:

  • 使用new Node代替。

  • 如果您不能这样做,则至少可以在malloc返回的内存上进行新的位置(new (ptr) Node())。

  • 使用智能指针和make_sharedmake_unique。这样,您甚至不需要照顾释放记忆。

  • 最好的方法可能是使用std::vector(如另一个答案中建议)或std::array

由于您使用的是vector&lt;>,因此您应该始终避免使用malloc且免费

但是,很少有需要使用新/删除,因为向量在相似的内存和访问足迹的情况下完成了相同的事情。

此实现将node包装在向量中,并消除直接内存分配,因为它是通过向量&lt;>自动完成的,同时保持了相同的传统用法样式。

#include <iostream>
#include <vector>
using namespace std;
struct node {
    int key;
    vector<int> connections;
};
int main(void) {
    // original with similar memory footprint and access characteristics using modern C++ vector<>
    int size = 10;
    vector<node> A(size);
    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;
        }
    }
    return 0;
}

可能是因为malloc不调用node的构造函数。由于这是C ,因此node不是C中的结构,而是一个类。它具有一个隐式构造函数,需要在实例化时调用。这意味着向量也无法正确创建。

您应该做2件事:

  1. 避免致电新,在这种情况下不需要,只需使用node A[10]或更好的std::vector<node> A
  2. 如果您不能这样做,请务必在C 中使用new,以便正确创建对象。

如果您绝对必须使用malloc,则需要调用placement new以构建您的结构(new (&A[0]) node()),因此实际上只是不使用malloc

未设置节点内的连接。这是因为您使用malloc创建YR节点实例。这只是为您提供了原始的非初始化内存。您必须使用新的来分配C 程序中的对象,而不是Malloc。新的分配内存然后运行构造函数

IE

node *A = new Node();

并删除以释放它 - 不免费

实际上您需要一个节点对象。那做本说的。制作它们的向量

但是,无论如何,除非您真的确定自己在做什么

最新更新