c++ - C ++ 11中不稳定的内存分配
问题描述
我的软件结果不稳定,我想了解为什么以及如何修改我的代码以获得一致的结果。为了展示这一点,我准备了一个软件的模拟样本;下面,我有 2 个主要课程,Mother
并且Daughter
;这些是我的主要数据结构,我Mother
在许多其他数据结构中使用。因此,它本质上是一个抽象类,但不能是纯抽象的,因为一些可观察对象也直接依赖于它,所以我不能在其中编写(据我所知)纯虚函数。类定义如下;
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include <vector>
using namespace std;
class Mother {
private:
double some_var_;
public:
Mother() {some_var_ = 0.;}
virtual ~Mother() {}
virtual void print() const
{
std::cout << "printing from mother " << some_var_ << std::endl;
}
virtual void setvar(double v) {some_var_ = v;}
virtual const double var() const {return 0.;}
};
class Daughter : public Mother
{
private:
double new_var_;
public:
Daughter() {new_var_ = 0.;}
virtual ~Daughter() {}
void print() const
{
std::cout << "printing from Daughter " << new_var_ << std::endl;
}
void setvar(double v) {new_var_=v;}
const double var() const {return new_var_;}
};
collection
我通过如下定义的类与这些数据结构进行交互;
class collection
{
private:
std::vector<Daughter> daughters_;
public:
collection () {Reset();}
virtual ~collection() {}
void Reset() {daughters_.clear();}
Daughter* GetNewDaughter()
{
daughters_.push_back(Daughter());
return &daughters_.back();
}
const std::vector<Daughter>& daughters() {return daughters_;}
};
鉴于这些,我定义了一个filter
函数来修剪这些数据结构;
template <class T, typename FN>
std::vector<const T*> filter(std::vector<T> objects, FN func)
{
std::vector<const T*> filtered;
for (auto &obj: objects)
{
if (func(&obj)) filtered.push_back(&obj);
}
return filtered;
}
代码体如下;
int main(int argc, char** argv)
{
collection* col = new collection();
for (unsigned int i=0; i<5; i++)
{
Daughter* current = col->GetNewDaughter();
current->setvar(double(i)*2.);
}
std::vector<const Daughter*> filt1 = filter(col->daughters(),
[] (const Daughter* d) {return d->var() > 2.;});
std::vector<const Daughter*> filt2;
for (unsigned int i=0; i<col->daughters().size(); i++)
{
const Daughter * current = &(col->daughters())[i];
if (current->var() > 2.) filt2.push_back(current);
}
std::cout << "first filtered" << std::endl;
for (const Daughter * c: filt1) c->print();
std::cout << "second filtered" << std::endl;
for (const Daughter * c: filt2) c->print();
return 0;
}
如您所见,我定义了两个过滤器,一个使用filter
函数,另一个手动定义,我希望看到相同的结果。但是,我运行了 4 次代码,每次都得到不同的结果;
g++ -Wall -std=c++11 -O3 -fPIC main.cpp -o main
$ ./main
first filtered
printing from Daughter 4
printing from Daughter -2.68156e+154
Segmentation fault: 11
$ ./main
first filtered
printing from Daughter 4
printing from Daughter 0
Segmentation fault: 11
$ ./main
first filtered
printing from Daughter 4
printing from Daughter 2.31584e+77
Segmentation fault: 11
$ ./main
first filtered
printing from Daughter 4
printing from Daughter 6
printing from Daughter 8
second filtered
printing from Daughter 4
printing from Daughter 6
printing from Daughter 8
如您所见,由于某种原因,前 3 次运行完全是垃圾,而最后一次运行符合预期,但它似乎完全是随机的,所以我相信我在内存分配期间做错了。如果有人能告诉我我做错了什么以及为什么做错了,我应该如何更改代码以避免这种不稳定,我将不胜感激。
谢谢!
解决方案
尝试改变:
std::vector<const T*> filter(std::vector<T> objects, FN func)
至
std::vector<const T*> filter(const std::vector<T>& objects, FN func)
恕我直言,您在调用过滤器时创建了向量的新实例(副本)。您“过滤”该向量的新实例,在过滤器完成后,该向量被删除,因此 std::vector<const Daughter*> filt1 具有无效指针。
推荐阅读
- git - 如何在 git push to remote 中启用详细模式
- github - 用 GitHub 实现 GitFlow:正确的方法是什么?
- javascript - 将极小极大函数从 Java 转换为 JavaScript
- android - 为 Android Studio 4.0 将我的 Android 手机连接到我的计算机
- ejabberd - STUN-TURN 服务器端口范围风险
- spring - 为什么`@PreAuthorize` 不保护我的服务方法?
- c# - 如何在 MVC RouteConfig 中设置默认语言?
- sql - 如何在间隔中添加分钟和秒
- postgresql - 从数据库 postgres 切换到 smart_brain 后关系不存在
- python - Python 问题:CS Circles 7C Loops, Square Census