首页 > 解决方案 > 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 次运行完全是垃圾,而最后一次运行符合预期,但它似乎完全是随机的,所以我相信我在内存分配期间做错了。如果有人能告诉我我做错了什么以及为什么做错了,我应该如何更改代码以避免这种不稳定,我将不胜感激。

谢谢!

标签: c++c++11

解决方案


尝试改变:

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 具有无效指针。


推荐阅读