【问题标题】:How to avoid Memory Leak with returning const char *如何通过返回 const char * 避免内存泄漏
【发布时间】:2016-04-23 11:50:40
【问题描述】:

我有一个函数在我的代码中使用了一百万次,但其中存在内存泄漏。

它将const wchar_t* 作为输入并返回const char*。 现在我知道返回的指针 (const char*) 需要从调用函数中获得显式的 delete[](但我负担不起),因为这意味着我需要在所有位置更改它。

代码如下:

inline const char * W2N(const wchar_t* wstr)
{
  int cw=lstrlenW(wstr);

  if (cw==0) 
  {
      CHAR *psz=new CHAR[1]; *psz='\0'; return psz;
  }

  int cc=WideCharToMultiByte(CP_ACP,0,wstr,cw,NULL,0,NULL,NULL);
  if (cc==0) return NULL;

  CHAR *psz=new CHAR[cc+1];
  cc=WideCharToMultiByte(CP_ACP,0,wstr,cw,psz,cc,NULL,NULL);
  if (cc==0) 
  {
      delete[] psz; return NULL;
  }

  psz[cc]='\0';
  return psz;
}

我可以围绕这个函数做些什么来避免内存泄漏。

【问题讨论】:

  • 同意bi303,但最后返回的指针psz导致泄漏,因为它从未被释放。
  • 你知道客户端调用函数什么时候会用完W2N()返回的内存吗?
  • 为什么不用std::string 而不是char *
  • 通过使用分配内存的函数,您“签署合同”并负责在必要时解除分配。您的代码状况不佳,任何棘手的解决方案都会使情况变得更糟。更改代码,使您的函数返回 std::unique_ptr<char[]> fact(new char[size]);(假设您在 C++ 环境中)或返回 std::string

标签: c++ memory-leaks


【解决方案1】:

您可以而且应该将指针包裹在std::unique_ptr<char[]> 中。这将以惯用的 C++ 方式解决您的确切问题。

这将像这样改变你的功能:

inline std::unique_ptr<char[]> W2N(const wchar_t *wstr) {
    int cw = lstrlenW(wstr);

    if(cw == 0) {
        auto psz = std::make_unique<char[]>(1);
        psz[0] = '\0';
        return psz;
    }
    int cc = WideCharToMultiByte(CP_ACP, 0, wstr, cw, NULL, 0, NULL, NULL);
    if(cc == 0)
        return nullptr;
    auto psz = std::make_unique<char[]>(cc + 1);
    cc = WideCharToMultiByte(CP_ACP, 0, wstr, cw, psz, cc, NULL, NULL);
    if(cc == 0) {
        return nullptr;
    }
    psz[cc] = '\0';
    return psz;
}

当然,这假设您可以访问符合 C++14 的编译器(对于 std::make_unique),或至少符合 C++11 的编译器(对于 std::unique_ptr)。

当然,如 cmets 中所述,您可以返回 std::string。如果这样做,请注意从函数返回 nullptrNULL 可能会出现段错误。

【讨论】:

    【解决方案2】:

    如果不尝试为多线程解决这个问题,一个足够大的全局 char 缓冲区可以容纳您的最大字符串并且返回的 \0 会导致固定的“泄漏”。

    【讨论】:

    • 虽然它会起作用,但我真的不建议将它用于除尝试避免动态内存分配的嵌入式环境之外的任何东西。这是在 Windows 操作系统 API 等的上下文中寻找麻烦,因为 OP 正在使用它。 (它也在嵌入式中寻找麻烦,但有时在那种环境中没有其他方法......)
    • 我应该为多线程、多进程、检查缓冲区溢出、编码还是更多?
    • 不,但你不应该在 WinAPI 应用程序中建议一个全局缓冲区,其中有一个事件循环和各种不太明显的控制可以流动的方式或各种可能意外变异的不透明函数你的缓冲区。
    • 那么这是Windows中需要修复的错误——怀疑它。
    • 不,这不是 Windows 中的错误。这只是让不打自己的脚变得更加困难。所有 Windows 功能都按预期工作,但是如果您开始拥有可以从任何地方更改并为之生存的全局缓冲区,您很容易忘记开发人员(Windows 和您的应用程序的功能)所承诺的内容并得到意想不到的结果计划的持续时间。
    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 2018-04-08
    相关资源
    最近更新 更多