Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic memory/realloc string array

Tags:

arrays

c

memory

Looking to create a dynamic array of string values.

In the example code below, the intention was for a new array item to be added (realloc) and a new string ("string 3") to be added to the array at runtime.

I imagine the issue is either improper use of pointers and/or something wrong with the realloc logic?

Appreciate any help.

The actual output I'm getting:

Before: 
Array[0]: string 1
Array[1]: string 2
After: 
Array[0]: string 1
Array[1]: string 2

The code:

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

char **myArray;

main(int argc, char *argv[])
{
    int i = 0;
    myArray = malloc(2 * sizeof(char*));
    int arrayIndexs = sizeof(*myArray) / sizeof(char*);

    //Allocate memory for each [x]
    for (i = 0; i <= arrayIndexs; i++)
        myArray[i] = malloc(254 * sizeof(char*));
    //Populate initial values
    if(myArray != NULL)
    {
        strcpy(myArray[0], "string 1");
        strcpy(myArray[1], "string 2");
    }
    //Print out array values
    printf("Before: \n");
    for (i = 0; i <= arrayIndexs; i++)
        printf("Array[%d]: %s\n",i, myArray[i]);

    //Expand array to allow one additional item in the array
    myArray = (char **)realloc(myArray, sizeof(myArray)*sizeof(char*));

    //Allocate memory for the new string item in the array
    myArray[arrayIndexs+1] = malloc(254 * sizeof(char*));

    //Populate a new value in the array
    strcpy(myArray[arrayIndexs+1], "string 3"); //

    arrayIndexs = sizeof(*myArray)/sizeof(char*);

    //Print out array values
    printf("After: \n");
    for (i = 0; i <= arrayIndexs; i++)
        printf("Array[%d]: %s\n",i, myArray[i]);
}
like image 310
MrDB Avatar asked Feb 22 '14 05:02

MrDB


2 Answers

If you ever find yourself attempting to use sizeof() for anything that is sized dynamically, you're doing it wrong. Keep that in mind. sizeof() is used repeatedly in this code incorrectly. Dynamic size counts must be managed by you; the allocation size requirements in bytes can be managed using those counts in conjunction with a sizeof() of the fundamental type for the item being stored.

Given that:

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

int main(int argc, char *argv[])
{
    int i = 0;
    int arrayIndexes = 2;
    char ** myArray = malloc(arrayIndexes * sizeof(*myArray));

    //Allocate memory for each [x]
    for (i = 0; i < arrayIndexes; i++)
    {
        myArray[i] = malloc(254 * sizeof(char));
        sprintf(myArray[i], "string %d", i+1);
    }

    //Print out array values
    printf("Before: \n");
    for (i = 0; i < arrayIndexes; i++)
        printf("Array[%d]: %s\n", i, myArray[i]);

    // TODO: Fix this to check the result before orphaning the old
    //  value of myArray if an allocation failure ensues.
    myArray = realloc(myArray, (arrayIndexes+1) * sizeof(*myArray));
    ++arrayIndexes;

    //Allocate memory for the new string item in the array
    myArray[arrayIndexes-1] = malloc(254 * sizeof(char*));

    //Populate a new value in the array
    strcpy(myArray[arrayIndexes-1], "string 3"); //

    //Print out array values
    printf("After: \n");
    for (i = 0; i < arrayIndexes; i++)
        printf("Array[%d]: %s\n",i, myArray[i]);

    // TODO: write proper cleanup code just for good habits.
    return 0;
}

Output

Before: 
Array[0]: string 1
Array[1]: string 2
After: 
Array[0]: string 1
Array[1]: string 2
Array[2]: string 3
like image 180
WhozCraig Avatar answered Oct 20 '22 02:10

WhozCraig


You shall replace this line:

arrayIndexs = sizeof(*myArray)/sizeof(char*);

by something like this:

arrayIndexs += 1;

Reason: sizeof is a compile-time operator to determine the size of a datatype or datatype of an object, while here you shall manually maintain the array size.

EDTIED: Also when initializing the variable, you shall use

int arrayIndexs = 2;

instead of

int arrayIndexs = sizeof(*myArray) / sizeof(char*);
like image 32
starrify Avatar answered Oct 20 '22 02:10

starrify