Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. How to pass a 2D array without memory issue ?
QtWS25 Last Chance

How to pass a 2D array without memory issue ?

Scheduled Pinned Locked Moved Unsolved C++ Gurus
9 Posts 3 Posters 3.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    TremblayGIS
    wrote on last edited by VRonin
    #1

    Hello,
    i am working on image analysis.
    I need to transfert the pixels values into an array for specific grid analysis.

    So i have a function in an external class called gdalfile like this :

    GDAL FILE**

    float **gdalfile::GetFileAsAnArray()
     {
    
    .....
         float *pafScanline;
    .....
     // nbPixel = nb column * nb line
    //pafScanline  is a buffer used by the gdal librairie to get the image value
         pafScanline = (float *) CPLMalloc(sizeof(float)*nbPixel);
    
    // GDAL function which put the pixel value in pafScanline 
     ....
    //--> SO FAR NO PROBLEM
    
    
    // Creat the array
     int count(0);
     int nColonnes=nXSize;
     int  nLignes=nYSize;
    
    //dynamic 2D array
     float **t;
      t = new float* [ nLignes ];
      for (int i=0; i < nLignes; i++)
        t[i] = new float[ nColonnes ];
    
     // fill the array with pafScanline value
      for (int i=0; i < nLignes; i++)
        for (int j=0; j < nColonnes; j++)
        {
        t[i][j] = pafScanline[count];
        count++;
        }
    
      return t ;
    

    Here is the main.cpp
    MAIN**

    //constructors 
    ........
    
    // Get the array values
    
        float** p= gdalTest.GetFileAsAnArray();
    
    //Some analysis
         for (int i=0; i < gdalTest.getYLine(); i++)
           for (int j=0; j < gdalTest.getXColonne(); j++)
           {
    
           p[i][j]= .......
    ......
    
           }
    

    After around 100000 loop, i got this :
    ERROR 2: CPLMalloc(): Out of memory allocating 65536 bytes.

    I guess this comes from the way i pass mya array.

    Could you help me ?

    Regards

    jsulmJ 2 Replies Last reply
    0
    • T TremblayGIS

      Hello,
      i am working on image analysis.
      I need to transfert the pixels values into an array for specific grid analysis.

      So i have a function in an external class called gdalfile like this :

      GDAL FILE**

      float **gdalfile::GetFileAsAnArray()
       {
      
      .....
           float *pafScanline;
      .....
       // nbPixel = nb column * nb line
      //pafScanline  is a buffer used by the gdal librairie to get the image value
           pafScanline = (float *) CPLMalloc(sizeof(float)*nbPixel);
      
      // GDAL function which put the pixel value in pafScanline 
       ....
      //--> SO FAR NO PROBLEM
      
      
      // Creat the array
       int count(0);
       int nColonnes=nXSize;
       int  nLignes=nYSize;
      
      //dynamic 2D array
       float **t;
        t = new float* [ nLignes ];
        for (int i=0; i < nLignes; i++)
          t[i] = new float[ nColonnes ];
      
       // fill the array with pafScanline value
        for (int i=0; i < nLignes; i++)
          for (int j=0; j < nColonnes; j++)
          {
          t[i][j] = pafScanline[count];
          count++;
          }
      
        return t ;
      

      Here is the main.cpp
      MAIN**

      //constructors 
      ........
      
      // Get the array values
      
          float** p= gdalTest.GetFileAsAnArray();
      
      //Some analysis
           for (int i=0; i < gdalTest.getYLine(); i++)
             for (int j=0; j < gdalTest.getXColonne(); j++)
             {
      
             p[i][j]= .......
      ......
      
             }
      

      After around 100000 loop, i got this :
      ERROR 2: CPLMalloc(): Out of memory allocating 65536 bytes.

      I guess this comes from the way i pass mya array.

      Could you help me ?

      Regards

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @TremblayGIS What loop do you mean? Do you have a loop in main where you constantly allocating memory? You can just free the memory before allocating new:

      for(...) {
      float** p= gdalTest.GetFileAsAnArray();
      
      //Some analysis
      for (int i=0; i < gdalTest.getYLine(); i++)
      for (int j=0; j < gdalTest.getXColonne(); j++)
      {
      
         p[i][j]= .......
      }
      delete[] p;
      }
      ......
      
         }
      
      

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • T TremblayGIS

        Hello,
        i am working on image analysis.
        I need to transfert the pixels values into an array for specific grid analysis.

        So i have a function in an external class called gdalfile like this :

        GDAL FILE**

        float **gdalfile::GetFileAsAnArray()
         {
        
        .....
             float *pafScanline;
        .....
         // nbPixel = nb column * nb line
        //pafScanline  is a buffer used by the gdal librairie to get the image value
             pafScanline = (float *) CPLMalloc(sizeof(float)*nbPixel);
        
        // GDAL function which put the pixel value in pafScanline 
         ....
        //--> SO FAR NO PROBLEM
        
        
        // Creat the array
         int count(0);
         int nColonnes=nXSize;
         int  nLignes=nYSize;
        
        //dynamic 2D array
         float **t;
          t = new float* [ nLignes ];
          for (int i=0; i < nLignes; i++)
            t[i] = new float[ nColonnes ];
        
         // fill the array with pafScanline value
          for (int i=0; i < nLignes; i++)
            for (int j=0; j < nColonnes; j++)
            {
            t[i][j] = pafScanline[count];
            count++;
            }
        
          return t ;
        

        Here is the main.cpp
        MAIN**

        //constructors 
        ........
        
        // Get the array values
        
            float** p= gdalTest.GetFileAsAnArray();
        
        //Some analysis
             for (int i=0; i < gdalTest.getYLine(); i++)
               for (int j=0; j < gdalTest.getXColonne(); j++)
               {
        
               p[i][j]= .......
        ......
        
               }
        

        After around 100000 loop, i got this :
        ERROR 2: CPLMalloc(): Out of memory allocating 65536 bytes.

        I guess this comes from the way i pass mya array.

        Could you help me ?

        Regards

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #3

        @TremblayGIS If this array always has same dimensions, then no need to allocate all the time: just allocate once and then fill it with data.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by VRonin
          #4

          p[i][j]= ....... the problem is somewhere in the ....... part. Looks like you are having a memory leak that is eating away all your available RAM.

          on the other hand, this is 2017 and it's C++, why are you using such a convoluted code?

          #include <boost/multi_array.hpp>
          #include <memory>
          #include <cassert> //optional, for assert()
          boost::multi_array<float, 2> gdalfile::GetFileAsAnArray(){
          const int nColonnes=nXSize;
          const int  nLignes=nYSize;
          std::unique_ptr<float[]> pafScanline(new float[nbPixel]);
          // GDAL function which put the pixel value in pafScanline (use pafScanline.get() for the raw pointer)
          assert(nLignes*nColonnes<=nbPixel);
          boost::multi_array<float, 2> t(boost::extents[nLignes][nColonnes]);
          int count=0;
          for (int i=0; i < nLignes; i++)
              for (int j=0; j < nColonnes; j++)
                  t[i][j] = pafScanline[count++];
          }
          return t;
          }
          

          or if you don't want to use boost:

          #include <vector>
          #include <memory>
          #include <cassert> //optional, for assert()
          std::vector< std::vector<float> > gdalfile::GetFileAsAnArray(){
          const int nColonnes=nXSize;
          const int  nLignes=nYSize;
          std::unique_ptr<float[]> pafScanline(new float[nbPixel]);
          // GDAL function which put the pixel value in pafScanline (use pafScanline.get() for the raw pointer)
          assert(nLignes*nColonnes<=nbPixel);
          std::vector<std::vector<float> > t(nLignes, std::vector<float>(nColonnes));
          int count=0;
          for (int i=0; i < nLignes; i++)
              for (int j=0; j < nColonnes; j++)
                  t[i][j] = pafScanline[count++];
          }
          return t;
          }
          

          @jsulm said in How to pass a 2D array without memory issue ?:

          delete[] p;

          Small note, malloc needs free, not delete

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          4
          • T Offline
            T Offline
            TremblayGIS
            wrote on last edited by
            #5

            Thank you so much for your help
            i'm gone a try that !

            regards

            1 Reply Last reply
            1
            • T Offline
              T Offline
              TremblayGIS
              wrote on last edited by TremblayGIS
              #6

              Hello, in fact i tried tis


              cpp :


              ...

              // 2D : column & lines dimensions
                   const int nColonnes;
                   const int  nLignes;
              
               //array. nbPixel = nLignes*nColonnes
                  float pafScanline[nbPixel];
              
                  // fill pafScanline with trivial value
                    for(int i(0); i<nbPixel; ++i)
                    {
                        pafScanline[i] = i*3 ;
                    }
              
              //fill  vector with pafScanline  
               std::vector<std::vector<float> > t(nLignes, std::vector<float>(nColonnes));
               int count=0;
               for (int i=0; i < nLignes; i++)
                   for (int j=0; j < nColonnes; j++)
                      {
                       t[i][j] = pafScanline[count++];
                      }
              
              return t
              

              main :


              int compteur(0);
              std::vector< std::vector<float> > p;
              p= gdalTest.GetFileAsAnArray();
              
               for (int i=0; i < gdalTest.getYLine(); i++)
                 for (int j=0; j < gdalTest.getXColonne(); j++)
                 {
                 p[i][j]= p[i][j]+1500;
                 compteur++;
                     qDebug()<< p[i][j];
                 }
              
              

              but after a while my program crashed (compteur = about 100 000 ) i got a crashed. i gess it's due to a memory issue.

              so i tried this to optimize the memory by passing the reference not the values :


              CPP :


              std::vector<std::vector<float> >* gdalfile::GetFileAsAnArray()
               {
              // 2D : column & lines dimensions
                   const int nColonnes;
                   const int  nLignes;
              
               //array. nbPixel = nLignes*nColonnes
                  float pafScanline[nbPixel];
                
                  // fill pafScanline with trivial value
                    for(int i(0); i<nbPixel; ++i)
                    {
                        pafScanline[i] = i*3 ;
                    }
              
              std::vector<std::vector<float> >* t(nLignes, std::vector<float>(nColonnes)); 
              
               int count=0;
              //loop to fill the vector
               for (int i=0; i < nLignes; i++)
               {
                     t[i]=new std::vector<float>(nColonnes);
                   for (int j=0; j < nColonnes; j++)
                      {
                       t[i][j] = pafScanline[count++];
                      }
              }
              
                return t ;
              

              I GOT THIS ERROR :
              // D:\Documents\codeblocks\testTableau\gdalfile.cpp|43|error: expression list treated as compound expression in initializer [-fpermissive]|
              //D:\Documents\codeblocks\testTableau\gdalfile.cpp|43|error: cannot convert 'std::vector<float>' to 'std::vector<std::vector<float> >*' in initialization|

              would you have some ideas about what is wrong. I just want to pass the reference of the vector in order to avoid to copy it.

              Regards

              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by VRonin
                #7

                this std::vector<std::vector<float> >* t(nLignes, std::vector<float>(nColonnes)); should become auto* t=new std::vector<std::vector<float> >(nLignes, std::vector<float>(nColonnes)); and this t[i]=new std::vector<float>(nColonnes); should be t[i]=std::vector<float>(nColonnes); but this will not improve anything in your program. std::vector is move constructable and move assignable so it doesn't make a copy when you call p= gdalTest.GetFileAsAnArray();

                your problem is somewhere else as the piece of code that crashes does not allocate any memory. Since you removed all my assertions from your code I'll have to ask you to check what nbPixel , nLignes and nColonnes contain

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                1 Reply Last reply
                1
                • T Offline
                  T Offline
                  TremblayGIS
                  wrote on last edited by TremblayGIS
                  #8

                  Ok thank you for your prompt help
                  i'm gone a try that
                  regards

                  VRoninV 1 Reply Last reply
                  1
                  • T TremblayGIS

                    Ok thank you for your prompt help
                    i'm gone a try that
                    regards

                    VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #9

                    @TremblayGIS said in How to pass a 2D array without memory issue ?:

                    i'm gone a try that

                    Try what? my point was that you code does not need to be changed but that the error was coming from somewhere else, like nbPixel ,nLignes or nColonnes

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    1

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved