字符串内存分配中可能存在内存泄漏

Posted

技术标签:

【中文标题】字符串内存分配中可能存在内存泄漏【英文标题】: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 标准库)。 【参考方案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 如果他打算读取二进制数据,可能不适合

以上是关于字符串内存分配中可能存在内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

Android的内存泄漏

Android的内存泄漏

Android内存泄漏

Java内存泄漏

安卓内存泄漏8种可能

iPhone - 内存分配略有增加