Thread: dynamic allocation of 2D array with different types in columns

  1. #1
    Registered User
    Join Date
    Apr 2011
    Posts
    74

    dynamic allocation of 2D array with different types in columns

    Hi all,

    I have a text file (tab delimited). This file contains a set of records. Each line is one record. Imagine that column headers have the following types.

    (char*) (uint8_t) (uint32_t) (uint16_t) (uint16_t)

    There are n_cols number of columns and there are certain number of rows, let's say n_rows.

    To allocate memory for such an 2D array, I have used the following function, where numByteInfo is an array which stores the size info (in bytes) for each column. This array has n_cols entries. numByteInfo[i] contains the size for ith column.

    Code:
    void** __allocate2D(uint8_t nrows, uint8_t ncolumns, int numByteInfo[]) 
    {
    		void** header;
        header = (void**) malloc(ncolumns * sizeof(void *));
    
    		printf("nrows %d, ncolumns %d\n", nrows, ncolumns);	
    
        if (!header) 
    		{
          printf("\n**TOP LEVEL ERROR****\n");
       		return NULL;
    		}
    
    		for (uint8_t i=0; i<ncolumns; i++) {
    
    			printf("numByteInfo[%d]: %d ", i, numByteInfo[i]);			
    		
    			header[i] = (void*) malloc(nrows * numByteInfo[i]);
    		
    			if (!header[i]) {
    				printf("\n***ERROR****\n");
    				return NULL;
    			}
    		}
    
    	return header;
    }

    And for deallocation, I use:

    Code:
     void __deallocate2D(void** header, uint8_t cols) {
    	for (uint8_t i=0; i<cols; i++) {
    		free(header[i]);
    	}
    	free(header);
    }
    Following this, I am allocating an array in the following function.

    Code:
    signed char some_function(void*** MY_ARRAY_RET, int* num_rows) {
    
    void** MY_ARRAY;
    int n_rows;
    
    
           // assuming I have a way to find the n_rows
    
    	MY_ARRAY = __allocate2D(n_rows, n_cols, numByteInfo);
       
          // storing some values
         char singleMessage[250];
         char val_0[20];    
         uint8_t val_1 = 0;
        uint32_t val_2 = 0;
        uint16_t val_3 = 0;
        uint16_t val_4= 0;
    
    uint8_t i = 0;
    while ( fgets(singleMessage, sizeof(singleMessage), file) ) 
    {
        sscanf(........., val_0, &val_1, &val_2, &val_3, &val4);
       
    
       *(char**)(MY_ARRAY[0] + i) = val_0;   
    *(uint8_t*)(MY_ARRAY[1] + i) =  val_1;				 
    *(uint32_t*)(MY_ARRAY[2] + i) =val_2; 
    *(uint16_t*)(MY_ARRAY[3] + i) = val_3;
    *(uint16_t*)(MY_ARRAY[4] + i) = val_4;
    i++;
    }
    
    *MY_ARRAY_RET = MY_ARRAY;
    *num_rows = n_rows;
    }
    While inside the function some_function, I am able to print the contents of each column of MY_ARRAY, and I can see that corresponding values are stored. However, I am unable to retrieve the values in main() function.

    Code:
     
    int main(int argc, char* argv[]) {
    
    
        void **EXAMPLE_ARRAY = 0; 
       int r = 0;
    		ret = some_function(&EXAMPLE_ARRAY, &r);
    
    for (uint8_t i = 0; i < r; i++) {
    
        printf("Hello: ""%s" " "
    					 "%" PRIu8 " " 
    					 "%" PRIu32 " "
    					 "%" PRIu16 " " 
    					 "%" PRIu16 " " 
           	     "\n", 
    					*(char**)(EXAMPLE_ARRAY[0]+ i),
    					*(uint8_t*)(EXAMPLE_ARRAY[1]+ i),
    					*(uint32_t*)(EXAMPLE_ARRAY[2]+ i),
    					*(uint16_t*)(EXAMPLE_ARRAY[3]+ i),
    					*(uint16_t*)(EXAMPLE_ARRAY[4]+ i)
               );
    }
    
    	__deallocate2D(EXAMPLE_ARRAY, 5);
    return 0;
    }
    The program compiles, I can print the value while in the some_function, but, cannot do that in main function.

    What can be the problem here.

    thanks,

    Zahid

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,798
    > *(char**)(MY_ARRAY[0] + i) = val_0;
    This does NOT make a copy of your local array.

    All you end up with is a bunch of pointers to the same memory location, which is also undefined when you eventually return to main.

    Your first column need to point to sufficiently long string buffers you can strcpy() into.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    Quote Originally Posted by zahid990170 View Post
    Hi all,

    I have a text file (tab delimited). This file contains a set of records. Each line is one record. Imagine that column headers have the following types.

    (char*) (uint8_t) (uint32_t) (uint16_t) (uint16_t)

    There are n_cols number of columns and there are certain number of rows, let's say n_rows.

    To allocate memory for such an 2D array, I have used the following function, where numByteInfo is an array which stores the size info (in bytes) for each column. This array has n_cols entries. numByteInfo[i] contains the size for ith column.

    Code:
    void** __allocate2D(uint8_t nrows, uint8_t ncolumns, int numByteInfo[]) 
    {
    		void** header;
        header = (void**) malloc(ncolumns * sizeof(void *));
    
    		printf("nrows %d, ncolumns %d\n", nrows, ncolumns);	
    
        if (!header) 
    		{
          printf("\n**TOP LEVEL ERROR****\n");
       		return NULL;
    		}
    
    		for (uint8_t i=0; i<ncolumns; i++) {
    
    			printf("numByteInfo[%d]: %d ", i, numByteInfo[i]);			
    		
    			header[i] = (void*) malloc(nrows * numByteInfo[i]);
    		
    			if (!header[i]) {
    				printf("\n***ERROR****\n");
    				return NULL;
    			}
    		}
    
    	return header;
    }

    And for deallocation, I use:

    Code:
     void __deallocate2D(void** header, uint8_t cols) {
    	for (uint8_t i=0; i<cols; i++) {
    		free(header[i]);
    	}
    	free(header);
    }
    Following this, I am allocating an array in the following function.

    Code:
    signed char some_function(void*** MY_ARRAY_RET, int* num_rows) {
    
    void** MY_ARRAY;
    int n_rows;
    
            // The first column is allocated 20 bytes for each of its element
    	int numByteInfo[10] = {20, 1, 4, 2, 2, 1, 1, 4, 8, 1};
    
           // assuming I have a way to find the n_rows
    
    	MY_ARRAY = __allocate2D(n_rows, n_cols, numByteInfo);
       
          // storing some values
         char singleMessage[250];
         char val_0[20];    
         uint8_t val_1 = 0;
        uint32_t val_2 = 0;
        uint16_t val_3 = 0;
        uint16_t val_4= 0;
    
    uint8_t i = 0;
    while ( fgets(singleMessage, sizeof(singleMessage), file) ) 
    {
        sscanf(........., val_0, &val_1, &val_2, &val_3, &val4);
       
    
       *(char**)(MY_ARRAY[0] + i) = val_0;   
    *(uint8_t*)(MY_ARRAY[1] + i) =  val_1;				 
    *(uint32_t*)(MY_ARRAY[2] + i) =val_2; 
    *(uint16_t*)(MY_ARRAY[3] + i) = val_3;
    *(uint16_t*)(MY_ARRAY[4] + i) = val_4;
    i++;
    }
    
    *MY_ARRAY_RET = MY_ARRAY;
    *num_rows = n_rows;
    }
    While inside the function some_function, I am able to print the contents of each column of MY_ARRAY, and I can see that corresponding values are stored. However, I am unable to retrieve the values in main() function.

    Code:
     
    int main(int argc, char* argv[]) {
    
    
        void **EXAMPLE_ARRAY = 0; 
       int r = 0;
    		ret = some_function(&EXAMPLE_ARRAY, &r);
    
    for (uint8_t i = 0; i < r; i++) {
    
        printf("Hello: ""%s" " "
    					 "%" PRIu8 " " 
    					 "%" PRIu32 " "
    					 "%" PRIu16 " " 
    					 "%" PRIu16 " " 
           	     "\n", 
    					*(char**)(EXAMPLE_ARRAY[0]+ i),
    					*(uint8_t*)(EXAMPLE_ARRAY[1]+ i),
    					*(uint32_t*)(EXAMPLE_ARRAY[2]+ i),
    					*(uint16_t*)(EXAMPLE_ARRAY[3]+ i),
    					*(uint16_t*)(EXAMPLE_ARRAY[4]+ i)
               );
    }
    
    	__deallocate2D(EXAMPLE_ARRAY, 5);
    return 0;
    }
    The program compiles, I can print the value while in the some_function, but, cannot do that in main function.

    What can be the problem here.

    thanks,

    Zahid
    I have updated the code to show
    Code:
    	int numByteInfo[10] = {20, 1, 4, 2, 2, 1, 1, 4, 8, 1};
    I am expecting that , 20 bytes are allocated to each element in first column.

    thanks,
    Zahid

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,798
    Maybe so, but you still need to use strcpy(), not pointer assignment.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    getting a segmentation fault while trying to

    Code:
    strcpy( *(char**)(MY_ARRAY[0] + i) , val_0);

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by zahid990170 View Post
    getting a segmentation fault while trying to

    Code:
    strcpy( *(char**)(MY_ARRAY[0] + i) , val_0);
    Your pointer arithmetic isn't going to know that you've allocated 20 bytes for each one of these things; plus, you'll need to make the type of MY_ARRAY[x] the right type before you do the pointer arithmetic, not after (true for all the lines, not just this one). So maybe something like
    Code:
    *(((char *)MY_ARRAY[0]) + numByteInfo[0]*i)

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,798
    TBH, your allocator is backwards.

    You allocate the major dimension as columns, then allocate large blocks for nRows.

    Then rely on some hooky maths (which is wrong) to divide up those blocks.

    FWW, I think you should start with
    Code:
    struct record {
        char field1[20];
        uint8_t field2;
        uint32_t field3;
        uint16_t field4;
        uint16_t field5;
    };
    Where you start with
    MY_ARRAY = malloc( nRows * sizeof(struct record) );


    When you're happy this works, then you can maybe think about your 'do it yourself struct' based on your numByteInfo array.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Apr 2011
    Posts
    74
    Quote Originally Posted by Salem View Post
    TBH, your allocator is backwards.

    You allocate the major dimension as columns, then allocate large blocks for nRows.

    Then rely on some hooky maths (which is wrong) to divide up those blocks.

    FWW, I think you should start with
    Code:
    struct record {
        char field1[20];
        uint8_t field2;
        uint32_t field3;
        uint16_t field4;
        uint16_t field5;
    };
    Where you start with
    MY_ARRAY = malloc( nRows * sizeof(struct record) );


    When you're happy this works, then you can maybe think about your 'do it yourself struct' based on your numByteInfo array.
    thank you,
    yes, I was allocating columns as major dimension.
    I think, it is much less complicated to go with the option of using a struct. I will try this.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. dynamic allocation of 2-D array
    By Yifangt in forum C Programming
    Replies: 6
    Last Post: 03-16-2016, 02:36 PM
  2. Dynamic array allocation
    By abhishekd18 in forum C Programming
    Replies: 7
    Last Post: 10-22-2012, 08:01 PM
  3. Dynamic array Allocation
    By deepak_j in forum C Programming
    Replies: 3
    Last Post: 08-17-2009, 07:18 AM
  4. dynamic 2D array allocation
    By deprekate in forum C Programming
    Replies: 5
    Last Post: 03-03-2009, 04:25 AM
  5. Dynamic 3D array allocation
    By Vulcan in forum C++ Programming
    Replies: 4
    Last Post: 11-21-2001, 02:51 AM

Tags for this Thread