【问题标题】:do I must release memory for "string* settings = new string[4]" in c++ in linux?我必须在 linux 的 c++ 中为“string* settings = new string[4]”释放内存吗?
【发布时间】:2011-10-05 04:21:32
【问题描述】:

我目前正在调试一些在 linux OS (centos 5) 中运行的遗留 c++ 程序。这些程序都调用类静态成员函数来获取数据库连接设置。这个类是这样编码的

class DbSetting {
    public:
        static string* getDbSettings();
};

string* DbSetting::getDbSettings() {
    string* settings = new string[4];
    settings[0] = "dbname";
    settings[1] = "server";
    settings[2] = "username";
    settings[3] = "password";
    return settings;
}

在每个程序的main()函数中,都会像这样调用这个静态函数,

int main(int argc, char* argv[]) {

    string* dbSettings = DbSetting::getDbSettings();

    //dbSettings is used to construct a db connection string

    return 0;
}

dbSettings 用于构造数据库连接字符串。但是,它不是“删除”(例如“delete[] dbSettings”)。我的问题是这是潜在的内存泄漏问题吗?这种用法也存在于许多其他遗留的 c++ 程序中。我对此感到困惑。希望有人能给我一个答案。谢谢!

【问题讨论】:

    标签: c++ linux pointers memory-leaks


    【解决方案1】:

    确实是内存泄漏。这是一个小问题,因为无论如何您的数据都需要在程序结束时保持活动状态,并且在程序终止时它会被清理 - 但它会导致内存泄漏检测器出现误报,所以这通常是一个好主意无论如何都要妥善清理;如果您让自己依赖操作系统清理,当您确实需要诊断内存泄漏时,您会发现有数百个误报需要整理!将代码重构为更大系统的一部分也非常困难,在该系统中它可能在同一个进程中多次启动和停止。

    避免这种情况的最简单方法是使用vector

    std::vector<string> DbSetting::getDbSettings() {
        std::vector<string> settings(4);
        settings[0] = "dbname";
        settings[1] = "server";
        settings[2] = "username";
        settings[3] = "password";
        return settings;
    }
    
    int main(int argc, char* argv[]) {
    
        std::vector<string> dbSettings = DbSetting::getDbSettings();
    
        //dbSettings is used to construct a db connection string
    
        return 0;
    }
    

    vector 会在你从 main 返回时,当它被销毁时,自动清理其中的字符串数组使用的内存。它还具有许多原始数组所没有的非常方便的功能 - 例如,它可以跟踪数组大小,并且可以在您使用 push_back 添加新元素时自动调整数组大小。

    【讨论】:

    • 如果可以使用c++11,array&lt;string,4&gt;会更合适。
    • 恕我直言,最好重写 getDbSettings,将 std::vector 作为参考参数返回,而不是返回值。它将减少向量的一个冗余复制。
    • @zabulus,当您返回在这样的自动变量中创建的对象时,在大多数情况下,编译器可以优化掉副本(调用者提供用于放置结果的内存,而被调用者构造对象进入该区域)
    • @bdonlan,这个优化是隐式的,这不是好事
    • @zabulus,这通常被认为是好的风格。特别是,C++0x 通过允许(通过右值引用移动语义)接近 RVO 的东西来进一步鼓励这一点,即使您正在分配给现有变量。
    【解决方案2】:

    基本上答案是肯定的。你应该delete[] 字符串。

    如果只从main()方法调用这个方法,至少泄漏内存不会变大,而是保持在4*sizeof(string)+为字符串数据保留的内存量,这在实践中通常不是问题。操作系统将处理出口处的泄漏。出于风格原因,您仍然应该 delete[] 它,因为其他人可能会更频繁地使用此类方法。如果他们只是复制和粘贴这样的代码,你很快就会发现问题!

    【讨论】:

      【解决方案3】:

      如果你通过引用参数传递getDbSettings()的结果会更好:

      void DbSetting::getDbSettings(std::vector<std::string> &result) {
          result.clear();
          result.push_back("dbname");
          result.push_back("server");
          result.push_back("username");
          result.push_back("password");
      }
      
      int main(int argc, char* argv[]) {
        std::vector<std::string> dbSettings;
        DbSetting::getDbSettings(dbSettings);
        return 0;
      }
      

      好处是显而易见的:不需要内存分配轨道。此外,为了将结果从函数传回,使用的临时对象也较少。返回 std::vector&lt;std::string&gt; 时,函数结束时将复制回临时数组(在禁用 RVO 的情况下)。它对返回的大量数据更加敏感,但最好总是这样做。

      【讨论】:

        【解决方案4】:

        是的,这是内存泄漏。在使用 new() 之后使用 delete[] 始终是一个好习惯。您可以使用智能指针来避免内存泄漏。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-13
          • 2012-01-02
          • 1970-01-01
          • 2015-11-21
          • 2013-06-05
          • 1970-01-01
          相关资源
          最近更新 更多