包含向量指针的结构的内存释放问题

时间:2018-10-18 21:55:13

标签: c++

我正在Linux环境c ++中工作。这个简单的代码无法释放指针的内存,我不确定为什么。

如果我实现了为向量指针Var分配内存的代码,然后使用swap()方法正确地清除了向量数据以删除向量条目,那么它也不会释放结构指针。 因此,我将代码简化为您在下面看到的代码,并且在调用delete时仍无法释放内存。

使用向量可能会导致问题,因为没有已知大小,不确定如何解决。要么是标准库,要么没有必要将内存释放回操作系统。

    #include <vector>

    typedef struct
    {
        char                Name[MAX_VAR_NAME_LEN + 1];    
        UINT8              *pValue;
    }DATA_STRUCT;

    typedef struct
    {
        char            SomeArray[SOME_MAX_ARRAY_SIZE;
        UINT16          VarCount;
        std::vector<DATA_STRUCT>  *Var;

    }SOME_STRUCT;

    int main(int argc, char* argv[])
    {
        SOME_STRUCT lpStruct* = new SOME_STRUCT;//lpStruct is allocated

        ///blah blah blah

        delete lpStruct;//lpStruct is not released

        return 1;
    }

1 个答案:

答案 0 :(得分:0)

您的主要问题似乎是为什么删除指针不会将指向地址设置为null。我将回答这个问题,但在回答结束时,请尝试使您对一些更现代的C ++样式睁开眼睛。


通常,您可以使用delete来自任何表达式(例如函数调用)的指针。在这种情况下,不可能将返回的指针设置为null:

Thing* getThingToDelete();
void main(){
    delete getThingToDelete();
    // how can delete set the returned pointer to null???
}

因此,如果您拥有一个有时允许为空的指针,则作为一种好习惯(但不是必需),将nullptr后的指针设置为delete,以书本形式:保持。这只是在处理指针和手动内存分配以及严格考虑所有权时要习惯的事情,正确使用newdeletenew[]和{{1} },检查delete[],并跟踪数组大小。确实,有很多事情要考虑,而且它很快就会妨碍您一开始就打算做的事情。出于这个原因,存在许多现代C ++功能,以隐藏所有这些噪声并照顾所有细节,而无需程序员的有意识干预。下面是一个示例。


考虑一下代码的现代修饰:

nullptr

请注意,我根本没有使用任何指针。此外,此代码没有内存泄漏,而且我从不需要考虑手动分配。如您所见,现代C ++允许您的程序比以前具有更丰富,更清晰的语义,并且仅需几行代码就可以完成许多常见任务。我的示例中出现了许多可能不熟悉的东西,我将提供指向此处的链接:

  • string-C型字符串的超简单,防白痴替代方法
  • vector-显然您已经看到了,但是文档显示了许多您可能不知道的有用的成员函数
  • iterators-标准库容器中的通用类似指针的访问器,可以与标准算法很好地配合使用
  • find_if and friends库中的
  • <algorithms>-适用于任何容器的便捷,通用的搜索功能
  • lambda expressions-匿名的局部函数,也可以引用局部变量
  • the auto keyword-自动推导变量的类型;可以为您省下很多的打字和维护工作
  • ranged for-loops-在容器中的所有元素上编写#include <vector> #include <string> #include <iostream> #include <algorithm> struct DATA_STRUCT { std::string Name; int Value; }; struct SOME_STRUCT { // I'm not sure if SomeArray is supposed to be used as a string or array // so here's both: std::string SomeString; std::vector<char> SomeCharArray; // the need for VarCount is unclear, but if you want to get the number // of elements in Var, you simply write: // > Var.size() std::vector<DATA_STRUCT> Var; }; int main(int argc, char** argv){ SOME_STRUCT s; // some example usage: // is there anything in s? bool hasAnyVars = !s.Var.empty(); // add a new value to s, with value=16 and name="Jeffrey" s.Var.push_back({ "Jeffrey", 16 }); // how many items are in s now? size_t numItems = s.Var.size(); // is there anyone named Helga? bool foundHelga = std::find_if(s.Var.begin(), s.Var.end(), [](const auto& x){ return x.Name == "Helga"; }) != s.Var.end(); // print every thing in the list for (const auto& x : s.Var){ std::cout << "Name=" << x.Name << ", value=" << x.Value << '\n'; } // end of examples return 1; } 循环的最短,最简单的方法

还请注意,如果您真的需要指针语义,例如对一个对象有多个引用,或者只是想管理一个多态对象的生存期,那么还有:

  • unique_ptr-一种智能指针,使用完后会自动删除自身。只有一个拥有者。
  • shared_ptr-可以具有多个引用的智能指针。当代码中的所有位置都使用完后会自动删除。

我确实没有大为改变您的名字,尽管如今很少见到用大写字母写的代码。有时让我担心,FORTRAN还是要对我大喊大叫,但这是我的主观感受,这实际上是个人喜好的问题。