C++ Valgrind抱怨使用依赖于未初始化字节的条件跳转
这个问题出现在我正在处理的一个较大程序的模块中,下面是一个小模拟:C++ Valgrind抱怨使用依赖于未初始化字节的条件跳转,c++,valgrind,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)*s
#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;
}
根据我的理解,问题在于向量的
push_back
函数中有一个if语句,它使用了一些未初始化的值。我不确定到底是什么。玩过之后,问题是我使用了malloc
。如果我使用calloc
我根本不会收到任何警告。如果我使用new
也一样。然而,在所有情况下,程序的行为方式完全相同。这里发生了什么?即使我收到所有这些警告,使用malloc是否安全?节点内的连接未设置。这是因为您使用malloc来创建您的节点实例。这只会给你未初始化的原始内存。必须使用新的方法来分配C++程序中的对象而不是MALLC。New分配内存,然后运行构造函数
即
并删除以释放它-不是免费的
实际上,您需要一个节点对象数组。照本说的做。做一个向量
<>但是无论如何,除非你确实知道你在做什么,否则永远不要在C++程序中使用MalC/C。这是因为您使用malloc来创建您的节点实例。这只会给你未初始化的原始内存。必须使用新的方法来分配C++程序中的对象而不是MALLC。New分配内存,然后运行构造函数 即 并删除以释放它-不是免费的 实际上,您需要一个节点对象数组。照本说的做。做一个向量
<>但是无论如何,在C++程序中永远不要使用MalC/C,除非你确实知道你在做什么[/P>,很可能是因为<代码> MaloC < /C> >不调用<代码>节点< /COD>的构造函数。因为这是C++,
node A[10]
或更好的std::vector A
如果绝对必须使用
malloc
,那么无论如何都需要调用placement new
来构造结构(new(&A[0])node()
),所以确实不要使用malloc
这可能是因为malloc
没有调用节点的构造函数。因为这是C++,节点< /COD>不是一个结构,因为它是C,它是一个类。它有一个隐式构造函数,需要在实例化时调用它。这意味着向量也没有正确创建
你应该做两件事:
避免调用new,在这种情况下没有必要,只需使用node A[10]
或更好的std::vector A
<>如果你不能做到这一点,在C++中总是使用<代码>新< /Cord>,以便正确创建对象。
如果绝对必须使用malloc
,那么无论如何都需要调用placement new
来构造结构(new(&A[0])node()
),所以确实不要使用malloc
不,在这里使用malloc
是不安全的
malloc
是分配内存的C方式。它不考虑C++构造函数。
calloc
也是C,但它会初始化内存。这就是为什么std::vector
起作用的原因(然而,这也是未定义的行为,因为可能有一个vector
实现需要初始化为零以外的值)
有很多方法可以解决这个问题:
- 改用
新节点
- 如果不能这样做,至少可以在
malloc
返回的内存上进行一次新的放置(new(ptr)Node()
)
- 使用智能指针和
使_共享
或使_唯一
。这样,你甚至不需要注意释放你的记忆
- 最好的方法可能是使用
std::vector
(如另一个答案中所建议的)或std::array
不,在这里使用malloc
是不安全的
malloc
是分配内存的C方式。它不考虑C++构造函数。
calloc
也是C,但它会初始化内存。这就是为什么std::vector
起作用的原因(然而,这也是未定义的行为,因为可能有一个vector
实现需要初始化为零以外的值)
有很多方法可以解决这个问题:
- 改用
新节点
- 如果不能这样做,至少可以在
malloc
返回的内存上进行一次新的放置(new(ptr)Node()
)
- 使用智能指针和
使_共享
或使_唯一
。这样,你甚至不需要注意释放你的记忆
- 最好的方法可能是使用
std::vector
(如另一个答案中所建议的)或std::array
因为您使用的是vector,所以应该始终避免malloc和free,因为它们不会初始化构造函数,而是使用new和delete以及智能指针
然而,很少需要使用new/delete,因为vector用相似的内存和访问空间完成同样的事情
此实现将节点
包装在一个向量中,并消除了直接内存分配,因为它是由向量自动完成的,同时保持了相同的传统使用方式
#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;
}
#包括
#包括
使用namesp
node *A = new Node();
#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;
}