zahra mahani
zahra mahani

Reputation: 59

allocate and free array in parallel loop with openmp in c

i have parallel loop which i allocate memory as an array and free that array at the end.

the problem is, when i want to free that, because of parallelism its not clear that i should free which array, that was created in parallel loops and i cant find current array size.

here is my code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>

/* PRIVATE FUNCTIONS */

static int split(char* input, char* delim, char** result,int array_idx);
/*******************************************************************************
***        FUNCTIONS DEFINITIONS
*******************************************************************************/
int parser(){

    
    int ids_size=3;
    long int_comma_size_arr[]={3,2,4};
    char* str_arr[]={"one,two,three","for,five","six,seven,eight,nine"};
    char* delim=",";
    

    #pragma omp parallel for 
    for(int i=0; i <ids_size; i++) {

        
        char* keys[int_comma_size_arr[i]];
        split(str_arr[i], delim, keys, 0 );

        #pragma omp parallel for 
        for (int n=0; n<int_comma_size_arr[i]; n++) {
            printf(keys[n]);
        }
        

        for (int m=0;m <int_comma_size_arr[i];m++){
            free(keys[m]);
        }
    }
}

/*******************************************************************************
***        PRIVATE FUNCTIONS
*******************************************************************************/
/* 
function name: split
stores array of strings which are chunks of input string, splited with delimiter.
*/
int split(char* input, char* delim, char** result,int array_idx) {
   
    char* found= strstr(input, delim);

    if (found==""||strlen(input)==0){
 
        return 0;

    }else if(found == NULL){
    
        result[array_idx]=malloc(strlen(input)+1 * sizeof(char));
        strncpy(result[array_idx], input, strlen(input));
        *(result[array_idx] + strlen(input)) = '\0';
        return 0;

    }else{

        int length = found - input;
        result[array_idx]=malloc((length+1) * sizeof(char));
        strncpy(result[array_idx], input, length);
        *(result[array_idx] + length) = '\0';
        return split(found+strlen(delim),delim,result,array_idx+1); 
    }
}

as you see, when i try to free for example the key which was created at i=0, in loop, the pointer of int_key_size_arr[i] points to int_key_size_arr[1].

i tried to solve this problem with replacing second for with next 2 options, but yet i get segmentation fault error.

as my keys size may be big, i prefer not to free all keys arrays at the end.

so how can i solve the problem of segmentation fault.

Upvotes: 0

Views: 152

Answers (1)

John Bollinger
John Bollinger

Reputation: 181907

If I rename your parser() function to main(), the resulting program runs fine for me, and Valgrind does not detect any incorrect memory accesses or frees.

Since you're asking about how to know how many of the split chunks to free, I assume your objective is to remove the code's reliance on the int_comma_size_arr array, which gives the number of chunks to expect for each input.

It would be easy enough to modify the split() function to return the total number of chunks allocated, and that would be a viable solution if you continue with storing the chunk pointers in an array. However, you are using int_comma_size_arr not only to know how many chunks to free, but also, in advance, how much storage to provide for the chunk pointers. You need to remove the latter dependency, too.

Possible solutions include:

  • Count appearances of the delimiter before actually performing the split, then use that to determine how many chunks to provide for and free.

  • Use the length of the input array as an upper bound on the number of chunks that will be found, and allocate enough space for that many chunks (some of which will go unused in most cases)

  • Dynamically allocate and reallocate space for the chunk array as you go, to adapt to the number of chunks actually found

  • Use a linked list or similar data structure to return the chunks, instead of an array (this also provides an alternative way to know how many to free)


Additionally,

  • Note that your found=="" condition will always evaluate to 0 (false), for two separate and independent reasons:

    1. The comparison tests whether the address stored in found is the same as the address of "", and under the circumstances, those addresses can never be equal.

    2. strstr() will return either a pointer to an appearance of the delimiter or a null pointer. Therefore, even if == were performing a content comparison ala strcmp(), the content could never match unless the delimiter were empty (which, pragmatically, your code does not support).

  • Your split() function duplicates the behavior of strdup() and strndup(). If you have one or both of these available to you, then using them would make split() much cleaner and clearer.

Upvotes: 2

Related Questions