gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master dff94fc 1/2: Match: correctly using string col


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master dff94fc 1/2: Match: correctly using string columns with --notmatched --outcols
Date: Sun, 27 Jun 2021 23:18:47 -0400 (EDT)

branch: master
commit dff94fc511f50f35a8b8a1e31a73fb7d80224914
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Match: correctly using string columns with --notmatched --outcols
    
    Until now, the newly added feature of appending non-matched columns of
    second input to first input was working fine with numbers, but when given
    string columns, it caused a segmentation fault. This was happening because
    string columns have a separately allocated space for each row and in the
    first implementation, I was mistakenly double-freeing them!
    
    With this commit, string columns have been given a special attention in the
    processing and the segmentation fault has been fixed.
---
 bin/match/match.c | 70 ++++++++++++++++++++++++++++++++++++++++++++-----------
 lib/match.c       |  3 ++-
 2 files changed, 59 insertions(+), 14 deletions(-)

diff --git a/bin/match/match.c b/bin/match/match.c
index b0a45fd..71850a3 100644
--- a/bin/match/match.c
+++ b/bin/match/match.c
@@ -156,7 +156,9 @@ match_catalog_read_write_all(struct matchparams *p, size_t 
*permutation,
                              size_t **numcolmatch)
 {
   int hasall=0;
+  char **strarr;
   gal_data_t *tmp, *cat;
+  size_t i, numnotmatched;
   gal_list_str_t *cols, *tcol;
 
   char *hdu              = (f1s2==1) ? p->cp.hdu     : p->hdu2;
@@ -224,18 +226,52 @@ match_catalog_read_write_all(struct matchparams *p, 
size_t *permutation,
                'realloc'ing). */
             if(p->notmatched)
               {
-                /* Move the non-matched rows after permutation to the top
-                   set of rows. */
+                /* We want to move the non-matched rows after permutation
+                   to the top set of rows. But when we have strings, the
+                   strings that will be over-written need to be freed
+                   first. */
+                numnotmatched = tmp->size - nummatched;
+                if(tmp->type==GAL_TYPE_STRING)
+                  {
+                    strarr=tmp->array;
+                    for(i=0;i<nummatched;++i)
+                      if(strarr[i]) free(strarr[i]);
+                  }
+
+                /* Move the non-matched elements up to the top. */
                 memcpy(tmp->array,
-                        gal_pointer_increment(tmp->array, nummatched,
-                                              tmp->type),
-                        nummatched*gal_type_sizeof(tmp->type));
+                       gal_pointer_increment(tmp->array, nummatched,
+                                             tmp->type),
+                       numnotmatched*gal_type_sizeof(tmp->type));
+
+                /* If we are on a string, the pointers at the bottom (that
+                   have been moved to the top), should not be set to NULL
+                   to avoid any potential double freeing. */
+                if(tmp->type==GAL_TYPE_STRING)
+                  {
+                    strarr=tmp->array;
+                    for(i=numnotmatched; i<tmp->size;++i) strarr[i]=NULL;
+                  }
 
                 /* Correct the size of the tile. */
-                tmp->size = tmp->dsize[0] = tmp->size - nummatched;
+                tmp->size = tmp->dsize[0] = numnotmatched;
               }
+
+            /* This is a normal match (not not-match). */
             else
-              tmp->size = tmp->dsize[0] = nummatched;
+              {
+                /* If we are on a string column, free the allocated space
+                   for each element that should be removed. */
+                if(tmp->type==GAL_TYPE_STRING)
+                  {
+                    strarr=tmp->array;
+                    for(i=nummatched;i<tmp->size;++i)
+                      if(strarr[i]) { free(strarr[i]); strarr[i]=NULL; }
+                  }
+
+                /* Correct the size. */
+                tmp->size = tmp->dsize[0] = nummatched;
+              }
           }
     }
 
@@ -280,8 +316,9 @@ static void
 match_catalog_write_one_row(struct matchparams *p, gal_data_t *a,
                             gal_data_t *b)
 {
-  size_t dsize=a->size+b->size;
+  char **strarr;
   gal_data_t *ta, *tb, *cat=NULL;
+  size_t i, dsize=a->size+b->size;
 
   /* A small sanity check. */
   if( gal_list_data_number(a) != gal_list_data_number(b) )
@@ -314,22 +351,29 @@ match_catalog_write_one_row(struct matchparams *p, 
gal_data_t *a,
                                   p->cp.quietmmap, ta->name, ta->unit,
                                   ta->comment);
 
-          /* Copy the data of the first input in output. */
+          /* Copy the data of the first and second inputs in output. */
           memcpy(cat->array, ta->array,
                  ta->size*gal_type_sizeof(ta->type));
-
-          /* Copy the data of the second input in output. */
           memcpy(gal_pointer_increment(cat->array, ta->size, cat->type),
                  tb->array, tb->size*gal_type_sizeof(tb->type));
 
+          /* If we have a string column, the allocated spaces of each row
+             should now only be freed within the 'cat' column, so set the
+             values within 'a' and 'b' to NULL. */
+          if(ta->type==GAL_TYPE_STRING)
+            {
+              strarr=ta->array; for(i=0;i<ta->size;++i) strarr[i]=NULL;
+              strarr=tb->array; for(i=0;i<tb->size;++i) strarr[i]=NULL;
+            }
+
           /* Increment 'tb'. */
           tb=tb->next;
         }
 
       /* Reverse the table and write it out. */
       gal_list_data_reverse(&cat);
-      gal_table_write(cat, NULL, NULL, p->cp.tableformat, p->out1name,
-                      "MATCHED", 0);
+      gal_table_write(cat, NULL, NULL, p->cp.tableformat,
+                      p->out1name, "MATCHED", 0);
       gal_list_data_free(cat);
     }
 
diff --git a/lib/match.c b/lib/match.c
index e2ec0d1..e3a4f34 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -853,7 +853,8 @@ gal_match_coordinates_output(gal_data_t *A, gal_data_t *B, 
size_t *A_perm,
   exit(0);
   */
 
-  /* Return the output. */
+  /* Clean up and return. */
+  free(Bmatched);
   return out;
 }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]