【问题标题】:C++ freeing dynamically allocated memory in shared library causing crashC ++释放共享库中动态分配的内存导致崩溃
【发布时间】:2022-01-12 18:30:46
【问题描述】:

我有一个共享库 mod.so,它有一个函数 getptr 来返回指向动态分配的内存的指针。它还有一个函数 Unload,它释放分配的内存。 主程序在运行时加载这个共享库,并从 getptr 获取指针 函数,但是当调用 Unload 函数时,它给了我分段错误。

ma​​in.cpp

    #include <iostream>
#include <dlfcn.h>
using namespace std;
int main()
{
  void* module = dlopen("mod.so",RTLD_LAZY);
  typedef int*(*func)();
  typedef void(*func1)();
  func f = (func)dlsym(module,"getptr");
  func1 b = (func1)dlsym(module,"Unload");
  int* p = f();
  b();
}

mod.cpp

    #include <iostream>
#include <vector>
using namespace std;
vector<int*> allocated;
extern "C"
{
  int* getptr()
  {
    int* p = new int;
    *p = 1024;
    allocated.push_back(p);
    return p;
  }
  void Unload()
  {
    for(auto e: allocated)
      delete e;
  }
}

mod.cpp 编译为:

g++ -shared mod.cpp -o mod.so -fPIC

【问题讨论】:

  • int* Unload() -- 当您应该返回 int* 时,您没有返回值 -- 未定义的行为。另外,你的编译器应该已经警告过你了。
  • 不,这不是程序崩溃的问题,即使我使用 void Unload()
  • 这是否能解决您的问题无关紧要——代码错误,如果不进行更改,您将无法更进一步。
  • Unload() 中,您不调用allocated.clear()。如果你多次使用Unload() 并由getptr() 交错,你可能会得到双释放(或空解引用)错误,除非你去掉你调用delete 的指针。如果你不多次使用Unload(),那为什么这段代码不在析构函数中呢?为什么要使用原始指针? vector&lt;unique_ptr&lt;int&gt;&gt; allocated; ...; allocated.push_back(make_unique&lt;int&gt;(1024)) 怎么样?这会自动处理您的释放。为什么要手动分配ints?为什么不vector&lt;int&gt; v; ...; return &amp;v.emplace_back(1024);
  • 在资源及其分配方面,以pairs 的形式创建函数始终是一个不错的设计选择:一个用于创建或分配,一个用于销毁或释放。跨度>

标签: c++ crash segmentation-fault shared-libraries shared-memory


【解决方案1】:

dlopen("mod.so",RTLD_LAZY) 返回 NULL。试试这个:

void* module = dlopen("./mod.so",RTLD_LAZY);
if (!module) {
    fprintf(stderr, "error in dlopen: %s\n", dlerror());
    return 1;
}

编辑:通过此修改,您的代码在 Linux/amd64 上使用 gcc-10.2 为我工作

请注意,如果您调用 Unload 两次, 会导致严重问题。可能的修复:

#include <iostream>
#include <vector>
using namespace std;
vector<int*> *allocated= NULL;
extern "C"
{
  int* getptr()
  {
    if (!allocated) allocated= new vector<int *>();
    int* p = new int;
    *p = 1024;
    allocated->push_back(p);
    return p;
  }
  void Unload()
  {
    if (allocated) {
      for(auto e: *allocated)
        delete e;
      delete allocated;
      allocated= NULL;
    }
  }
}

【讨论】:

  • 不,我已经检查过 dlopen() 不返回 NULL
  • 请编辑您的原始帖子并包含显示问题的实际minimal reproducible example。 (例如,如果您使用了一些 LD_LIBRARY_PATH env.var。请说明。)
猜你喜欢
  • 1970-01-01
  • 2010-09-25
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 2013-11-22
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
相关资源
最近更新 更多