使用太多内存进行文件解析(C ++)

时间:2011-11-09 09:04:23

标签: c++ file memory-management vector

我有一个程序可以从.raw文件中提取内容,这里有一个示例:

1.000000 1.000000 -1.000000 1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 -1.000000 1.000000 -1.000000 
1.000000 0.999999 1.000000 -1.000000 1.000000 1.000000 -1.000000 -1.000000 1.000000 0.999999 -1.000001 1.000000 
1.000000 1.000000 -1.000000 1.000000 0.999999 1.000000 0.999999 -1.000001 1.000000 1.000000 -1.000000 -1.000000 
1.000000 -1.000000 -1.000000 0.999999 -1.000001 1.000000 -1.000000 -1.000000 1.000000 -   1.000000 -1.000000 -1.000000 
-1.000000 -1.000000 -1.000000 -1.000000 -1.000000 1.000000 -1.000000 1.000000 1.000000 - 1.000000 1.000000 -1.000000 
1.000000 0.999999 1.000000 1.000000 1.000000 -1.000000 -1.000000 1.000000 -1.000000 -1.000000 1.000000 1.000000 

这些只是一个立方体的面,我的问题是,这个文件是650字节,现在当我加载程序时,程序占用20mb。这不是一个问题,但是当加载更大的文件时,它可能会成为一个大问题。

这是我的文件phraser的代码(对不起,如果它很乱,我是C ++的新手):

/*
 * PhraseObj.cpp
 *
 *  Created on: Nov 5, 2011
 *      Author: tom
 */

#include "PhraseObj.h"

#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "obj.h"

PhraseObj::PhraseObj(string file)
{
    FILE.open(file.c_str());
    cout << FILE.is_open() << "\n";
}

obj PhraseObj::getObj()
{
    string line;
    Polygon P;
    vertex V;
    obj O;
    int place;
    int NextPos;
    float x;
    float y;
    float z;
    getline(FILE, line);
    while (!FILE.eof()) {

        cout << "new line" << "\n";

        place = 0;
        while (place != string::npos) {
            if (place == (line.length() - 1)) {
                break;
            }

            NextPos = line.find(" ", place + 1);
            line.substr(place, (NextPos - place) - 1);
            cout << line.substr(place, (NextPos - place) - 1).c_str() << " ";
            x =::atof(line.substr(place, (NextPos - place) - 1).c_str());

            V.x(x);
            cout << x << "\n";

            place = NextPos;
            NextPos = line.find(" ", place + 1);
            line.substr(place, NextPos - place);
            cout << line.substr(place + 1, (NextPos - place) - 1).c_str() << " ";
            y =::atof(line.substr(place + 1, (NextPos - place) - 1).c_str());
            V.y(y);
            cout << y << "\n";

            place = NextPos;
            NextPos = line.find(" ", place + 1);
            line.substr(place + 1, NextPos - place);
            cout << line.substr(place + 1, (NextPos - place) - 1).c_str() << " ";
            z =::atof(line.substr(place + 1, (NextPos - place) - 1).c_str());
            V.z(z);
            cout << z << "\n";

            P.addPoint(V);
            place = line.find(" ", place + 1);
            cout << "place: " << place << " " << "length:" << line.length() << "\n";
        }
        getline(FILE, line);
        O.AddPolygon(P);
    }
    cout << "returning" << "\n";
    try {
        return O;
    }
    catch(bad_alloc & ba) {
        cout << "bad_alloc caught: " << ba.what() << endl;
    }
}

void PhraseObj::closeFile()
{
    FILE.close();
}

bool PhraseObj::isEnd()
{
    return FILE.eof();
}

一些注意事项,顶点是x,y和z浮点数 多边形是顶点的矢量 obj是多边形的向量。

谢谢,汤姆。

和vertex.h:

/*
 * vertex.h
 *
 *  Created on: Oct 26, 2011
 *      Author: tom
 */

#ifndef VERTEX_H_
#define VERTEX_H_


class vertex {
float x_;
float y_;
float z_;
public:
//here are some getters
float x() {return x_;} ;
float y() {return y_;} ;
float z() {return z_;} ;
// and now for some setters
void x(float _x) {x_ = _x;} ;
void y(float _y) {y_ = _y;} ;
void z(float _z) {z_ = _z;} ;
};


#endif /* VERTEX_H_ */

和polygon.cpp:

/*
 * Polygon.cpp
 *
 *  Created on: Oct 26, 2011
 *      Author: tom
 */

#include "Polygon.h"


using namespace std;

void Polygon::addPoint(vertex V) {
point.push_back(V);
}

int Polygon::getNumOfPoints() {
return point.size();
}

 vertex Polygon::getPoint(int I) {
return point.at(I);
 }

4 个答案:

答案 0 :(得分:1)

我不知道为什么你会看到过多的内存使用,所以这不是你问题的答案,但我想指出你可以通过以下方式简化你的PhraseObj::getObj()功能。使用std::istringstreamstd::istream_iterator个对象:

obj PhraseObj::getObj()
{
    obj O;
    string line;
    while ( getline( FILE, line ) ) {
        istringstream vertices( line );
        istream_iterator<double> it( vertices ), end;

        Polygon p;
        for ( int i = 0; i < 4; ++i ) {
            Vertex v;
            v.x( *it++ );
            v.y( *it++ );
            v.z( *it++ );
            p.addPoint( v );
        }

        O.AddPolygon( p );
    }        
}

您可以将字符串粘贴到std::string对象中,然后使用istringstream个对象迭代不同的顶点,而不是使用istream_iterator<double>方法从一个空格字符转到下一个空格字符。如果您知道每行总共有12个坐标顶点(每个顶点有3个顶点,每个多边形有4个顶点),那么您可以使用简单的循环来读取它们。

答案 1 :(得分:1)

从它的外观来看,你的代码并没有那么糟糕。我看到的唯一问题是,你创建了很多中间对象,每个都调用一些内存分配(因为你使用过RAII,好!),这不会导致内存泄漏。但是现代内存分配器不会立即将释放的内存返回给操作系统,而是保留它,以便从那里回答进一步的分配请求。所以你可能只是经历过这一点。

当然,你应该避免创建那些不需要的中间人。例如,您的代码包含大量line.substr(place + 1, NextPos - place);,您不会将结果字符串分配给任何内容。因此,std::string变为现实,并且在不被使用的情况下被破坏。

您还应该避免这种过多的调试输出,因为这会严重降低您的程序速度。它可以用于调试目的,但是一旦工作就应该删除或者删除它。

答案 2 :(得分:0)

如果将其保存为浮点数的二进制表示形式,则文件大小,加载时间,解析时间,内存等将显着下降。

只需使用当前的解析器将新文件输出为二进制浮点数(可能创建自定义构建脚本)。然后你可以有一个更小/更快的发行版,并将转换移动到内部。

答案 3 :(得分:0)

我能看到的唯一问题是,您在使用EOF阅读后正在测试getline(),您应该使用do ... while更改while循环。除此之外,此代码不是向我们展示的相关代码。可能是多边形顶点的类声明有很大机会运行内存泄漏......你是否正在使用STL的 vector&lt;&gt;

你必须考虑另一件事,因为你还没有告诉你如何得出浪费太多记忆的结论。也许这20 Mb是操作系统中任何进程的标准内存的一部分。如果您想真正了解内存的使用方式,则需要一个分析工具,例如 valgrind