1

I am trying to read mesh data from a fluent mesh file. The code works perfectly till it reads node data. While reading cell data, it exits randomly by giving random negative number or what() std::bad_alloc. I am not able to understand the reason behind this behaviour. Please help me to resolve the issue. I tried printing different variables, but it works perfectly just before it exits. Here is what I have been able to put together till now

#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>

int str_to_int( std::string s);
double str_to_double( std::string s);
int strhex_to_int(std::string s);
std::vector<std::string> convert_string_to_vector(std::string line);
void GetDimension();
void GetNodes();
void GetCells();
void GetFaces();
void GetBcNames();

std::ifstream meshFile ;
std::string fileLine;
std::vector<std::string> lineVector;
int nDim, nNodes, nCells, nFaces;
double *nodePoints;
int *cellData, *faceData;

int main()
{
    int property;
    meshFile.open("test.msh", std::ifstream::in);
    if (meshFile.is_open())
    {
        while ( !meshFile.eof() )
        {
            std::getline(meshFile,fileLine);
            //std::cout << fileLine << "\n";
            lineVector = convert_string_to_vector(fileLine);
            if(lineVector.empty())
                continue;
            else
                property = str_to_int( lineVector[0] );

            //std::cout << property << "\n";
            /*
            for(int j=0; j < lineVector.size(); j++)
            {
                std::cout << lineVector[j] << "\n";
            }
            */
            switch(property)
            {
                case 0:
                    std::cout << "Comment Detected\n";
                    lineVector.clear();
                    break;
                case 2:
                    GetDimension();
                    break;
                case 10:
                    GetNodes();
                    break;
                case 12:
                    GetCells();
                    break;
                case 13:
                    GetFaces();
                case 39:
                    GetBcNames();
                default:
                    std::cout << "Problem with mesh file\n";
            }
        }

    }
    else std::cout << "Unable to open file";
}

void GetDimension()
{
    nDim = str_to_int(lineVector[1]);
    std::cout << "Problem Dimension: " << nDim << "\n";
    lineVector.clear();
}

void GetNodes()
{
    int nodeZoneId, startNode, endNode, nodeType;
    std::string fileLine;
    nodeZoneId = str_to_int(lineVector[1]);
    if (nodeZoneId == 0)
    {
        nNodes = strhex_to_int( lineVector[3]);
        std::cout << "Total Nodes = " << nNodes << "\n";
        lineVector.clear();
        if (nDim ==  2)
            nodePoints = new double[nNodes*2];
        else
            nodePoints = new double[nNodes*3];
    }
    else
    {
        startNode = strhex_to_int( lineVector[2]);
        endNode = strhex_to_int( lineVector[3]);
        nodeType = str_to_int(lineVector[4]);
        std::cout << "Reading nodes from "<< startNode << " to " << endNode << " of type " << nodeType << " for zone = " << nodeZoneId << "\n";
        lineVector.clear();
        for( int j = startNode - 1; j < endNode; j++)
        {
            //std::cout << j << "\n";
            std::getline(meshFile,fileLine);
            if (fileLine.empty())
            {
                std::cout << "No Nodes found in file!" << "\n";
                break;
            }
            //std::cout << fileLine << "\n";
            lineVector = convert_string_to_vector(fileLine);

            if(lineVector.empty())
                j--;
            else
            {
                if(nDim == 2)
                {
                    //std::cout << lineVector[0] << "\t" << lineVector[1] << "\n";
                    nodePoints[0*nNodes + j] = str_to_double(lineVector[0]);
                    nodePoints[1*nNodes + j] = str_to_double(lineVector[1]);
                    std::cout << nodePoints[0*nNodes + j] << " " << nodePoints[1*nNodes + j] << "\n";
                    lineVector.clear();
                }
                else
                {
                    //std::cout << lineVector[0] << "\t" << lineVector[1] << "\t" << lineVector[2] << "\n";
                    nodePoints[0*nNodes + j] = str_to_double(lineVector[0]);
                    nodePoints[1*nNodes + j] = str_to_double(lineVector[1]);
                    nodePoints[2*nNodes + j] = str_to_double(lineVector[2]);
                    std::cout << nodePoints[0*nNodes + j] << " " << nodePoints[1*nNodes + j] << " " << nodePoints[2*nNodes + j] << "\n";
                    lineVector.clear();
                }
            }
        }
    }
    //std::getline(meshFile,fileLine);
    //std::cout << fileLine << "\n";
    //std::getline(meshFile,fileLine);
    //std::cout << fileLine << "\n";
    //lineVector.clear();
}

void GetCells()
{
    int cellZoneId, startCell, endCell, cellType;
    std::string fileLine;

    cellZoneId = str_to_int(lineVector[1]);
    //std::cout << cellZoneId << "\n";
    if (cellZoneId == 0)
    {
        nCells = strhex_to_int(lineVector[3]);
        //std::cout << "Total Cells = " << nCells << "\n";
        lineVector.clear();
        cellData = new int(nCells*2);
    }
    else
    {
        startCell = strhex_to_int(lineVector[2]);
        endCell = strhex_to_int(lineVector[3]);
        cellType = str_to_int(lineVector[5]);
        std::cout << "Reading cells from "<< startCell << " to " << endCell << " of type " << cellType << " for zone = " << cellZoneId << "\n";
        lineVector.clear();

        if(cellType != 0)
        {
            for(int j = startCell - 1; j < endCell; j++)
            {
                    cellData[0*nCells + j] = cellZoneId;
                    cellData[1*nCells + j] = cellType;
            }
        }
        else
        {
            for(int j = startCell - 1; j < endCell; j++)
            {
                std::getline(meshFile,fileLine);
                //std::cout << fileLine << "\n";
                if (fileLine.empty())
                {
                    //std::cout << "No Cells found in file!" << "\n";
                    break;
                }
                lineVector = convert_string_to_vector(fileLine);
                if(lineVector.empty())
                    j--;
                else
                {
                    int k = 0;
                    //std::cout << lineVector.size() << "\t" << k << "\n";
                    while(k < lineVector.size())
                    {
                        cellData[0*nCells + j] = cellZoneId;
                        //std::cout << j << "\t" << lineVector[k] << "\n";
                        cellData[1*nCells + j] = str_to_int(lineVector[k]);
                        k++;
                        std::cout << nCells*2 << "\t" << 0*nCells + j << "\t" << 1*nCells + j << "\n";
                        j++;
                    }
                    lineVector.clear();
                    j--;
                }
            }
        }
    }
}

void GetFaces()
{
    nDim = str_to_int(lineVector[1]);
    lineVector.clear();
}

void GetBcNames()
{
    nDim = str_to_int(lineVector[1]);
    lineVector.clear();
}

std::vector<std::string> convert_string_to_vector(std::string line)
{
    std::stringstream ss;
    std::vector<std::string> stringVector;
    stringVector.clear();
    ss << line;

    std::getline(ss, line);
    ss.clear();
    std::size_t prev = 0, pos;
    //std::cout << line << "\n";
    while ((pos = line.find_first_of(" ()", prev)) != std::string::npos)
    {
        //std::cout << prev << "\t" << pos << "\n";
        if (pos > prev)
        {
            //std::cout << line.substr(prev,pos-prev) << "\t";
            stringVector.push_back(line.substr(prev, pos-prev));
        }
        prev = pos+1;
    }
    //std::cout << "\n";
    if (prev < line.length())
        stringVector.push_back(line.substr(prev, std::string::npos));

    /*
    for(int j=0; j < stringVector.size(); j++)
    {
        std::cout << stringVector[j] << "\t";
    }
    std::cout << "\n";
    */
    return stringVector;
}

int str_to_int(std::string s)
{
    //std::cout << s << "\t";
    std::istringstream temps(s);
    int temp;
    temps >> temp;
    //std::cout << temp << "\n";
    return temp;
}

double str_to_double(std::string s)
{
    //std::cout << s << "\n";
    std::istringstream temps(s);
    double temp;
    temps >> temp;
    //std::cout << temp << "\n";
    return temp;
}
int strhex_to_int(std::string s)
{
    //std::cout << s << "\n";
    std::stringstream temps;
    temps << std::hex << s;
    int temp;
    temps >> temp;
    //std::cout << temp << "\n";
    return temp;
}

Also please indicate if there is a better way to do the same job with C++

The input file is huge so its uploaded here

https://drive.google.com/file/d/0Bz_4p6XclzrncU5BZG5MZUtNUmM/view?usp=sharing

  • 1
    `while ( !meshFile.eof() )` -- [Please read why using eof() is considered wrong](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – PaulMcKenzie Jan 12 '17 at 18:23
  • 1
    Not related to your problem, but I see a bunch of `new`s and no `delete`s. You've got memory leaks. Actually, `bad_alloc` probably points to other memory-related issues as well. Try compiling with the -g flag and running through `valgrind`. – 0x5453 Jan 12 '17 at 18:23
  • 2
    Welcome to Stack Overflow! It sounds like you may need to learn how to use a debugger to step through your code. With a good debugger, you can execute your program line by line and see where it is deviating from what you expect. This is an essential tool if you are going to do any programming. Further reading: **[How to debug small programs](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/)** – NathanOliver Jan 12 '17 at 18:25
  • 1
    Why are you not using `std::vector` here?: `nodePoints = new double[nNodes*2];`?. You have the tools, you included them (I see `#include `), but you failed to use them. – PaulMcKenzie Jan 12 '17 at 18:25
  • 1
    Please learn about smart pointers (`std::unique_ptr`, `std::shared_ptr`, `std::weak_ptr`). – Jesper Juhl Jan 12 '17 at 18:27
  • @PaulMcKenzie thank you :), I will modify that. – Sameer Karania Jan 14 '17 at 03:27
  • @0x5453 Is there a way to do this in code::blocks 13.12? – Sameer Karania Jan 14 '17 at 03:31
  • @NathanOliver Thank you, the article was very helpful. I tried debugging using Code::Blocks 13.12, and was unable to see anything unusual until it exited. I am new to this so will learn more about it and try again. – Sameer Karania Jan 14 '17 at 03:33
  • @PaulMcKenzie I have used vector only to split the string into individual elements. I want to use nodePoints later for certain calculations. I am not sure how to use vector there – Sameer Karania Jan 14 '17 at 03:54
  • @0x5453 I want to use the `new` s later for some calculations, I am not sure when and how to use `delete` s. I am trying to figure that out. Thanks for your comment. – Sameer Karania Jan 14 '17 at 03:56
  • @SameerKarania `std::vector nodePoints;...nodePoints.resize(nNodes * 2);` -- That's all you need to do. There is no need for `new[]` and `delete[]` in your program. Also `cellData = new int(nCells*2);` -- This is probably a mistake. You are allocating a single integer, not `nCells*2` integers. But why do that when here you can use `std::vector`? – PaulMcKenzie Jan 14 '17 at 06:45
  • @PaulMcKenzie ok. Thanks, I tried that and it works perfectly. I was not sure if I can use it like that. Thanks a lot. I would still like to ask if the method I am using is a good method to read the type of file I am reading or is there a better way to do it. – Sameer Karania Jan 15 '17 at 06:35
  • Thanks everyone, all your comments were very useful – Sameer Karania Jan 15 '17 at 06:35

0 Answers0