【问题标题】:Clear out the STL list of pointers in C++清除 C++ 中的 STL 指针列表
【发布时间】:2017-11-17 02:15:37
【问题描述】:

我已经定义了一个指针列表。在清除列表之前我应该​​如何释放所有这些指针?删除所有列表成员的最佳方法是什么?在下面的程序中,是否需要释放为 struct 分配的内存?请参阅我的内联 cmets。

struct MyStruct {
    char *data;
    int len;
};

typedef std::list<struct MyStruct *> myStruct_list;
myStruct_list l_list;

/* Prepare a list */

for( int i = 0; i < 10; i++) {
    struct MyStruct *s = (MyStruct *)malloc(sizeof(struct MyStruct));
    s->data = (char*)malloc(MAX_LEN);
    get_random_data(s->data,size);
    s->len = strlen(s->data);
    l_list.push_back(s);
}


/* Delete all members from a list */

myStruct_list::iterator it;
for (it = l_list.begin(); it != l_list.end(); ++it) {
    if (*it) {
        free(*it);       // --->> do I need to free (*it)->data ?????
    }
}
l_list.clear();

【问题讨论】:

  • 你为什么还要在这里使用指针?我认为没有理由这样做,如果您删除它们,那么您不必担心泄漏:)
  • 你为什么使用malloc?这段代码有一半看起来更像 c 而不是 c++。
  • std::list&lt;struct MyStruct *&gt;::iterator it; 对不起,你是过去的人吗?说真的,如果你在这里没有使用一些遗留系统,你真的需要更新你的学习材料。
  • 抱歉,这是示例程序。我刚开始学习C++。我想了解指针和 STL 容器。所以我写了示例程序。
  • s[len] = '\0'; 不会很好结束,与其自己分配和终止字符串,不如考虑使用std::string

标签: c++ list pointers stl


【解决方案1】:

我想了解一下下面的程序是否有内存泄漏?

是的,你就在这里:

p = (char*)malloc(MAX_LEN);
p = (char *)buf;

您分配内存并将其分配给p,下一行您将其释放。所以:

  1. 您不应在 C++ 程序中使用 malloc(),除非您需要传递将由 C 代码管理的数据
  2. 您应该使用std::string 等特殊数据结构来管理您的数据。
  3. 如果您仍需要分配动态内存,请使用智能指针。

如果有内存泄漏,我应该如何调试?

你不会一开始就创建它们。例如,你怎么写get_random_str(假设你真的必须使用malloc分配它):

using spchar = std::unique_ptr<char[], decltype(std::free) *>;

spchar get_random_str( int len )
{
    spchar s( static_cast<char *>( malloc( len + 1 ) ), std::free );
    static const char alphanum[] =  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
     for (int i = 0; i < len; ++i) {
         s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
     }

     s[len] = '\0';
     return s;
 }

注意,这段代码我没有编译,只是给你看思路。

更新:看起来你认为这段代码:

p = (char *)buf;

会将字符串从buf 复制到p,但情况并非如此。相反,您使p 指向buf 的内存,从而丢失malloc() 之前返回的旧值(因此造成内存泄漏),然后您将buf 的地址分配给data,这会在您调用@987654336 时导致UB @ 就可以了,所以你需要什么:

strncpy( p, buf, MAX_LEN );

但即使这样也没有必要,因为您根本不需要 buf

void myClass::fillData(void) 
{
    s = (MyStruct *)malloc(sizeof(struct MyStruct));
    s->data = (char*)malloc(MAX_LEN);
    get_random_str(s->data,950);
    s->len = strlen(s->data);
    l_list.push_back(s);
}

但这是更多的 C 代码,使用一些 C++ 语法。如果你真的想学习 C++,你应该得到更新的编译器和教科书。

【讨论】:

  • 你是对的。将来可能会被某些 C 代码使用。这就是我使用 malloc 的原因。
  • 您仍然可以使用智能指针和自定义删除器从 malloc 中释放内存。但更大的问题是你编写的是 C 代码,而不是 C++
  • @M.Rock 如果您正在编写代码以便将来可能被 C 使用,那么您正在编写 C 代码。如果您的代码不是 C,那么在移植时使用malloc 是您最不关心的问题。
  • 我分配给 p。然后我将此 p 分配给 struct 数据成员。所以我没有放弃它,但我有第一个指向这个的列表成员。我可以跟踪这一点。此外,在我的环境中,他们似乎还没有升级 g++。他们似乎仍在使用旧版本。所以不支持智能指针。
  • @M.Rock 你确实松了,我从你的问题中复制了两行代码,你将malloc 的结果分配给p,下一行你将buf 分配给p ,丢失了malloc 之前返回的内存地址。将buf 分配给p 会产生另一个问题——你用buf 调用std::free,这也是UB。看起来您想要的是 strcpy( p, buff ); 而不是 p = buff; 如果您想使用指针,请了解指针。
【解决方案2】:

使用for_each中的lambda函数删除元素:

std::for_each(l_list.begin(), l_list.end(), [](const MyStruct* elem){if(elem) free(elem)});

并明确指针:

l_list.clear();

【讨论】:

  • 更好的建议是使用std::unique_ptrs 中的std::list,这将保证在销毁列表时销毁指向的结构。当然,这是假设 OP 确实需要首先存储指向结构的指针...
  • 恕我直言“为什么我有内存泄漏?”的答案。应该是“因为您使用的是原始指针”。释放他们对抗的是症状而不是原因;)
  • 不是 dv,但 if(elem) 是多余的,在空指针上调用 free 是合法的。 (此外,几乎完全基于意见,但 std::for_each 与基于范围的 for 循环 for( const auto elem : l_list ) 相比显得有些臃肿)。
  • 为什么会被如此严厉地否决?它专门针对他们已经拥有的代码回答了操作问题...
猜你喜欢
  • 1970-01-01
  • 2010-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 2017-04-05
  • 1970-01-01
  • 2010-11-08
相关资源
最近更新 更多