Valgrind抱怨使用依赖于未初始化字节的条件跳转

时间:2016-12-21 17:50:14

标签: c++ 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是否安全?

4 个答案:

答案 0 :(得分:2)

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

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

calloc也是C,但它会初始化你的记忆。这就是std::vector工作的原因(然而,它也是未定义的行为,因为可能有一个vector实现需要初始化为零以外的其他内容。

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

  • 请改用new Node

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

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

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

答案 1 :(得分:1)

由于您使用的是vector&lt;&gt;,因此您应该始终避免使用malloc和free,因为它们不会初始化构造函数,而是使用new和delete和智能指针。

然而,很少需要使用new / delete,因为vector通过类似的内存和访问占用来实现相同的功能。

此实现将node包装在向量中并消除直接内存分配,因为它是由vector&lt;&gt;自动完成的。同时保持相同的传统使用方式。

#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;
}

答案 2 :(得分:0)

未设置节点内的连接。这是因为您使用malloc来创建您的Node实例。这只是给你原始的未初始化的内存。你必须使用new来分配c ++程序中的对象而不是malloc。 New分配内存然后运行构造函数

node *A = new Node();

并删除以释放它 - 不是免费的

实际上你需要一个Node对象数组。那样做是什么意思。制作一个矢量

但无论如何,除非你确定你知道自己在做什么,否则永远不要在c ++程序中使用malloc / free

答案 3 :(得分:0)

可能是因为malloc没有调用node的构造函数。由于这是c ++,node不是c中的结构,它是一个类。它有一个隐式构造函数,需要在实例化时调用。这意味着矢量也未正确创建。

你应该做两件事:

  1. 避免调用新内容,在这种情况下不需要使用node A[10]或更好std::vector<node> A
  2. 如果您不能这样做,请始终在c ++中使用new,以便正确创建对象。
  3. 如果你绝对必须使用malloc,那么你需要调用placement new来构建你的结构(new (&A[0]) node()),所以真的不要使用malloc