【问题标题】:Possible memory leak in string memory allocation字符串内存分配中可能存在内存泄漏
【发布时间】:2014-03-23 09:10:00
【问题描述】:

这是我的代码:

#include <string>
#include <iostream>

#include <cstdio>
#include <cstdlib>

std::string & fileread(const char * name)
{
    FILE *fp = fopen(name,"rb");
    size_t sz;
    int i;
    char *buff;
    fseek(fp, 0, SEEK_END);  
    sz = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    buff = (char *)malloc(sizeof(char)*(sz+1));
    buff[sz] = '\0';
    fread(buff,sz,1,fp); 
    std::string * rtstr = new std::string(buff);
    free(buff);
    fclose(fp);
    return * rtstr;
}

int main(int argc,char * argv[])
{
    std::string file_info(fileread(argv[1]));
    std::cout<<file_info << std::endl;
    return 0;
}

它只是读取一个文件,并将其内容打印到屏幕上。

在函数fileread 中,我使用new std::string(buff); 得到std::string *,并将点返回。会不会导致内存泄漏?如果答案是“是”,如何避免呢?


关于在 C++ 中使用 C:freadifstream 快得多(用 10 亿个随机数测试)

我的问题是关于内存泄漏。

【问题讨论】:

  • 不要在 C++ 中编码 C。使用std::ifstreamstd::string(不是std::string*)。
  • fread()std::ifstream::read() 一样快。再说一次,不要认为 C 在性能方面会获胜。 C++ 也同样出色,并且在某些情况下,性能优于 C
  • @Nawaz 请分享一些“比 C 性能更好”的好链接。
  • @SahilSareen C++ 类型系统鼓励静态类型检查和值语义,这两者都能带来更好的优化。例如,考虑std::sort()qsort():C 基于函数指针(CPU 管道的最大敌人之一),另一方面,C++ 基于模板和仿函数(也就是编译器内联所有内容)。跨度>
  • @SahilSareen:将使用指针(通常为void* 和函数指针)的任何代码通用 C 代码与使用模板的通用 C++ 代码进行比较。 C++ 最有可能比 C 更快。一个这样的例子是 std::sort(来自 C++ 标准库)与 qsort(来自 C 标准库)。

标签: c++ string memory-leaks stl


【解决方案1】:

按值返回 std::string。别担心,C++ 会注意不冗余地复制对象(除非你有一个非常旧的编译器)。 这是代码,已修复:

#include <string>
#include <iostream>

#include <cstdio>
#include <cstdlib>

std::string fileread(const char * name)
{
    FILE *fp = fopen(name,"rb");
    size_t sz;
    int i;
    char *buff;
    fseek(fp, 0, SEEK_END);  
    sz = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    buff = (char *)malloc(sizeof(char)*(sz+1));
    buff[sz] = '\0';
    fread(buff,sz,1,fp); 
    std::string rtstr(buff);
    free(buff);
    fclose(fp);
    return * rtstr;
}

int main(int argc,char * argv[])
{
    std::string file_info(fileread(argv[1]));
    std::cout<<file_info << std::endl;
    return 0;
}

我只做了必要的小改动,忽略了您的代码中可能遇到的任何其他问题。保重。

【讨论】:

  • [yu@argcv ex]$ g++ test.cc --std=c++11 test.cc: In function ‘std::string fileread(const char*)’: test.cc:22:12: error: no match for ‘operator*’ (operand type is ‘std::string {aka std::basic_string&lt;char&gt;}’) return * rtstr; ^
  • 如果只返回rtstr,则返回一个本地值。
  • @YuJing:它返回一个副本,而不是对局部变量的引用。
  • @Nawaz 和,我可能会从文件中读取 1GB 或更多 binary 数据,请您提供更多更好的建议吗?
  • return * rtstr; 行需要替换为return rtstr; 任何现代编译器都会执行返回值优化,因此不会进行复制。
【解决方案2】:

正如 Nawaz 正确评论的那样:“不要在 C++ 中编写 C 代码。使用 std::ifstream 和 std::string(不是 std::string*)”。这是避免所有问题的 C++ 代码:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main () {

  string line;
  ifstream myfile ("myfile.txt");

  if (myfile.is_open())
  {
    while ( getline (myfile,line) )
    {
      cout << line << '\n';
    }
    myfile.close();
  }

  else cout << "Unable to open file"; 

  return 0;
}

【讨论】:

  • 请注意,您不必使用myfile.close()。此外,if (myfile) 优于 if (myfile.is_open())
  • @Nawaz 我用它来正确关闭它。这样做不是一个好习惯吗?
  • 当流对象超出范围时,它将关闭文件。它是 RAII 对象。所以不用担心。
  • @SahilSareen:请参阅 my question on Code Review 关于这个确切问题。
  • std::getline 如果他打算读取二进制数据,可能不适合
猜你喜欢
  • 2011-05-14
  • 1970-01-01
  • 2014-04-30
  • 2016-09-12
  • 1970-01-01
  • 2011-07-18
  • 1970-01-01
  • 2010-12-21
  • 2019-08-12
相关资源
最近更新 更多