CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6

Thread: Seg fault error

  1. #1
    Join Date
    Mar 2009
    Posts
    1

    Seg fault error

    Hey I am writing a c++ program that takes in input from the command line of two files containing matrices. It then takes that and does matrix multiplication. The results are outputted to a file. When I compile using g++ I get a segmentation fault error. I have tried adding cout to find the source but to no avail. Here is the code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <vector>
    #include <iostream>

    using namespace std;

    float mat_sum(vector <vector<float> > mata,vector <vector<float> > matb, int row, int column, int rowc);

    int main (int argc, char *argv[])
    {
    vector <vector<float> > mata, matb, matc; //initalize matricies
    int rows, cols; //value for rows and columns input matrix
    int rowc, colc; //values for row and column output matrix
    float temp, sum;
    FILE *matrixa, *matrixb, *matrixc;
    matrixa=fopen(argv[0],"r");
    fscanf (matrixa,"%d %d", &rows, &cols);
    rowc=cols;
    cout<<rowc;
    for (int i=0; i<rows; i++){
    mata.push_back (vector<float>() );
    for (int j=0; j<cols; j++){
    fscanf (matrixa,"%f",temp);
    mata[i].push_back(temp);
    }
    }
    fclose (matrixa);


    matrixb=fopen(argv[1],"r");
    fscanf (matrixb,"%d %d", &rows, &cols);
    colc=rows;
    for (int i=0; i<rows; i++){
    matb.push_back (vector<float>() );
    for (int j=0; j<cols; j++){
    fscanf (matrixb,"%f",temp);
    matb[i].push_back(temp);
    }
    }
    fclose (matrixb);

    matrixc=fopen(argv[2],"w");
    fprintf (matrixc,"%d\n%d\n",rowc,colc);
    for (int i=0; i<rowc; i++){
    matc.push_back (vector<float>());
    for (int j=0; j<colc; j++){
    matc[i].push_back(mat_sum(mata,matb,i,j,rowc));
    fprintf(matrixc," %f",matc[i][j]);
    }
    fprintf(matrixc,"\n");
    }
    fclose(matrixc);
    return 0;
    }

    float mat_sum(vector <vector<float> > mata,vector <vector<float> > matb,int row,int column, int rowc){
    float sum=0;
    for (int i=0; i<rowc; i++){
    sum=sum+mata[row][i]*matb[i][column];
    }
    return sum;
    }

  2. #2
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: Seg fault error

    Use code tags when posting.

    Run it in the debugger.

  3. #3
    Join Date
    Apr 2007
    Location
    Mars NASA Station
    Posts
    1,436

    Re: Seg fault error

    Probably caused by buffer overflow.

    Alias you 2D array with typedef and initialize with fixed column and row and you can resize row with resize().
    Thanks for your help.

  4. #4
    Join Date
    Feb 2009
    Location
    Ukraine
    Posts
    64

    Re: Seg fault error

    At a first glance the following code runs into eyes:
    Code:
    fscanf (matrixb,"&#37;f",temp);
    The arguments to scanf() functions that follow the format string specification are addresses of the vars where the input should be stored. In the code above float temp is interpreted as a memory address, which of course (probably) is from unmapped region - and attempt to write might cause segfault.
    As you probably guess, you should write instead:
    Code:
    fscanf (matrixb, "%f", &temp);

  5. #5
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Seg fault error

    Firstly you should write some error checking code, how do you know you have been given three arguments? You should check this e.g.

    Code:
    if(argc!=4) //program name + three arguments  = 4 program arguments
    {
      std::cerr << "Usage: [program] [inMatrix1] [inMatrix2] [outMatrix]" << std::endl;
    }
    else
    {
      //...
    }
    Incidently, did you realise that argv[0] is not the first argument but the program name? Therefore your accessing of argv[0], argv[1] and argv[2] should be argv[1], argv[2] and argv[3] respectively. This is obviously a contributer to the problems you are having.

    Secondly, make sure you initialise your variables and preferably only declare one per line.

    Thirdly, when writing C++, please get into the habit of using the C++ file stream instead of C's FILE. You could then use istream to convert the next bit of data to a int, float or what ever else it needs to be directly and safely without attempting to use C functions such as fscanf - I expect your other problems are to do with misuse or abuse of these C functions.

    Fourthly, you could extract your read code into a function since you are effectively doing the same thing twice.

    Fifthly, consider exception safety...

    I have to go to lunch now, but if nobody else has replied by then, I'll help you with the code a bit more.
    Last edited by PredicateNormative; March 4th, 2009 at 09:41 AM.

  6. #6
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Seg fault error

    I'm now able to reply to this... so here are my thoughts. Firstly, as Peter_APIIT pointed out, a typedef wouldn't go amiss:

    Code:
    typedef std::vector<std::vector<float> > Vector2D;
    Now, as I previously mentioned, once you have checked that the number of arguments is equal to three, you want to read in the matrix data from the two files into two Vector2D's. Since the code to do this is the same for each matrix file, the code could be extracted into a function to save having to write it twice:

    Code:
    Vector2D readMatrix(const std::string& filename)
    {
      Vector2D matrix;
      std::ifstream infile(filename.c_str());
      float temp(0);
    
      int rows = NextIStreamValTo<int>(infile);
      int cols = NextIStreamValTo<int>(infile);
    
      for (int i=0; i<rows; i++){
        matrix.push_back (vector<float>() );
        for (int j=0; j<cols; j++){
          temp = NextIStreamValTo<float>(infile);
          matrix[i].push_back(temp);
        }
      }
      infile.close();
      return matrix;
    }
    The function NextIStreamValTo<T> converts the next bit of data from an istream to the type designated by T. The code looks like this:

    Code:
    template<typename T>
    T NextIStreamValTo(std::istream& s)
    {
      if(!s.good())
      {
        throw std::runtime_error("NextIStreamValTo failed : istream is not in a good state!");
      }
      T result;
      if(!(s>>result)) 
      {
        throw std::runtime_error("NextIStreamValTo failed : failed to convert data to desired type!");
      }
      return result;
    }
    Now that is covered, there is arguably a problem with the code I have just given you for readMatrix. Condsider what would happen if the line
    Code:
    std::ifstream infile(filename.c_str());
    failed to open the file given in the string filename. The std::ifstream constructor does not throw an exception if the open fails, so instead the code would carry on. The next thing that would happen is NextIStreamValTo<T> would throw an exception stating that the "istream is not in a good state!" because it could not read the istream. Although this exception message is true, it would be better to state why the istream is in a bad state, and for that an exception should be thrown at the point of failure:

    Code:
    Vector2D readMatrix(const std::string& filename)
    {
      Vector2D matrix;
      std::ifstream infile(filename.c_str());
      float temp(0);
    
      if(infile.is_open())
      {
          int rows = NextIStreamValTo<int>(infile);
          int cols = NextIStreamValTo<int>(infile);
    
          for (int i=0; i<rows; i++){
            matrix.push_back (vector<float>() );
            for (int j=0; j<cols; j++){
              temp = NextIStreamValTo<float>(infile);
              matrix[i].push_back(temp);
            }
          }
          infile.close();
      }
      else 
      {
        throw std::runtime_error("Cannot open file " + filename + " for reading!");
      }
      return matrix;
    }
    Now a lot of the logic is correctly handled, the main function outside of error checking and exception handling becomes:

    Code:
    Vector2D mata = readMatrix(argv[1]);
    Vector2D matb = readMatrix(argv[2]);
    Vector2D matc;
    
    int colc = mata.size();
    int rowc= matb[0].size();
          
    std::ofstream matrixc(argv[3]);
    matrixc << rowc << std::endl << colc << std::endl;
    for (int i=0; i<rowc; i++){
      matc.push_back (vector<float>());
      for (int j=0; j<colc; j++){
        matc[i].push_back(mat_sum(mata,matb,i,j,rowc));
        matrixc << matc[i][j] << " ";
      }
      matrixc << std::endl;
    }
    matrixc.close();
    Putting it all together then with error checking and exception handling, gives:
    Code:
    #include <iostream>
    #include <vector>
    #include <string>
    #include <fstream>
    #include <stdexcept> //for std::runtime_error
    
    using namespace std;
    typedef std::vector<std::vector<float> > Vector2D;
    
    template<typename T>
    T NextIStreamValTo(std::istream& s)
    {
      if(!s.good())
      {
        throw std::runtime_error("NextIStreamValTo failed : istream is not good!");
      }
      T result;
      if(!(s>>result)) 
      {
        throw std::runtime_error("NextIStreamValTo failed : failed to convert data to desired type!");
      }
      return result;
    }
    
    Vector2D readMatrix(const std::string& filename)
    {
      Vector2D matrix;
      std::ifstream infile(filename.c_str());
      float temp(0);
    
      int rows = NextIStreamValTo<int>(infile);
      int cols = NextIStreamValTo<int>(infile);
    
      for (int i=0; i<rows; i++){
        matrix.push_back (vector<float>() );
        for (int j=0; j<cols; j++){
          temp = NextIStreamValTo<float>(infile);
          matrix[i].push_back(temp);
        }
      }
      infile.close();
    
      return matrix;
    }
    
    float mat_sum(vector <vector<float> > mata,vector <vector<float> > matb, int row, int column, int rowc);
    
    int main (int argc, char *argv[])
    {
      if(argc!=4)
      {
        std::cerr << "Usage: [program] [inMatrix1] [inMatrix2] [outMatrix]" << std::endl;
      }
      else
      {
        try
        {
          Vector2D mata = readMatrix(argv[1]);
          Vector2D matb = readMatrix(argv[2]);
          Vector2D matc;
    
          int rowc = mata.size();
          int colc = matb[0].size();
          
          std::ofstream matrixc(argv[3]);
          matrixc << rowc << std::endl << colc << std::endl;
          for (int i=0; i<rowc; i++){
            matc.push_back (vector<float>());
            for (int j=0; j<colc; j++){
              matc[i].push_back(mat_sum(mata,matb,i,j,rowc));
              matrixc << matc[i][j] << " ";
            }
            matrixc << std::endl;
          }
          matrixc.close();
        }
        catch(std::exception& e)
        {
          std::cerr << e.what() << std::endl;
        }
        catch(...)
        {
          std::cerr << "Unknown exception caught" << std::endl;
        }
      }
      system("PAUSE");
      return 0;
    }
    
    float mat_sum(vector <vector<float> > mata,vector <vector<float> > matb,int row,int column, int rowc)
    {
      float sum=0;
      for (int i=0; i<rowc; i++){
        sum=sum+mata[row][i]*matb[i][column];
      }
      return sum;
    }
    Last edited by PredicateNormative; March 5th, 2009 at 03:33 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured