0

I'm trying to read a set of strings into an array. Therefore, I'm using a double pointer. Furthermore, I'm reallocing space to increase the double pointer's size if needed. I maintain the size of the double pointer at all times. However I get a non deterministic segmentation fault. For some inputs, the following program works. For others it doesn't. I've been able to isolate a case for when segmentation fault occurs but can't identify why I'm running into this fault:

// Maximum size of commands
#define MAX_COMMAND_LEN 30
// Initial size of instructions array
#define INIT_ARGS_SIZE 3
// Size 
#define REALLOC_MARGIN 10

// Function prototypes
int     getInput(char **instructionArray, int currentSize);
void    freeDoubleArray(int size, char **array);


int     main(int argc, char **argv) {

    char **instructions;

    instructions = (char**)calloc(INIT_ARGS_SIZE, sizeof(char*));

    int count = getInput(instructions, INIT_ARGS_SIZE);

    printf("\n Lets try the first string: %s\n", instructions[0]);

    // Print all strings in array of strings
    for (int i = 0; i < count; i++) {
        printf("String '%d' is '%s' for count %d\n", i, instructions[i], count);
        fflush(stdout);
    }

    freeDoubleArray(count, instructions);

    return (0);
}


/**
 * @brief Get instruction inputs from stdin
 * 
 * @param instructionArray - double pointer to read instruction strings into
 * @return int - return number of string sread in
 */
int     getInput(char **instructionArray, int currentSize) {

    int i = 0;
    char temp[MAX_COMMAND_LEN];

    while (fgets(temp, MAX_COMMAND_LEN, stdin) != NULL) {
        if (i >= currentSize - 1) {
            currentSize += REALLOC_MARGIN;
            instructionArray = (char **)realloc(instructionArray, currentSize * sizeof(char*));
        }

        // Initialize string at this index
        instructionArray[i] = (char*)calloc(strlen(temp) + 1, sizeof(char));
        // Copy string read in into instruction array at index
        strcpy(instructionArray[i], temp);
        // Length of string read in
        int length = strlen(instructionArray[i]);
        
        // Ignore all lines with a single white space (or single character)
        if (length <= 2) {
            fprintf(stderr, "Warning - Line %d is empty.\n", i);
            continue;
        }

        // Remove new line from the end of string
        // Special case for windows
        if (instructionArray[i][length - 1] == '\n' && instructionArray[i][length - 2] == '\r') {
            instructionArray[i][length - 1] = '\0';
            instructionArray[i][length - 1] = '\0'; 
        }
        // For all other OS
        else 
            if (instructionArray[i][length - 1] == '\n')
                instructionArray[i][length - 1] = '\0';
        
        // Test output - ensure data is being written and accessible
        printf("String '%d' is '%s' for i %d\n", i, instructionArray[i], i);
        i++;
    }

    return (i);
}


/**
 * @brief Free double char pointer
 * 
 * @param size - size of double pointer
 * @param array - double char pointer
 */
void    freeDoubleArray(int size, char **array) {

    // Loop through and free all indeces
    for (int i = 0; i < size; i++)
        free(array[i]);

    // Free top level pointer
    free(array);
}

Here's the case which gives me a segmentation fault:

asdasldlaksdj aklsdfjkl
askdlfjsalkdf sdfasd
sdflksjd fsa
dfajslkdfj salkdjf as
dfjksladjf s adf
a sdflkjsa dflaskdjf 
asjdkfjas dklfjaslkd f
asdflksjdf as
dfsdkfjalskdf 
sadfjksadjf sd
fsdjfkljasdf asdfjksd 
asdjfklsja df
asdjflk sdf
asdjdfkl sjdfsdf
asdlkfj skdfj a
sdjfklsaj df
asdf sjakldfj 
asdjfkasjlfjsald 
asdflkjsdf  asldkjf 
askldfjas ldflk

Here's the console output:

./a.out < test    
String '0' is 'asdasldlaksdj aklsdfjkl' for i 0
String '1' is 'askdlfjsalkdf sdfasd' for i 1
String '2' is 'sdflksjd fsa' for i 2
String '3' is 'dfajslkdfj salkdjf as' for i 3
String '4' is 'dfjksladjf s adf' for i 4
String '5' is 'a sdflkjsa dflaskdjf ' for i 5
String '6' is 'asjdkfjas dklfjaslkd f' for i 6
String '7' is 'asdflksjdf as' for i 7
String '8' is 'dfsdkfjalskdf ' for i 8
String '9' is 'sadfjksadjf sd' for i 9
String '10' is 'fsdjfkljasdf asdfjksd ' for i 10
String '11' is 'asdjfklsja df' for i 11
String '12' is 'asdjflk sdf' for i 12
String '13' is 'asdjdfkl sjdfsdf' for i 13
String '14' is 'asdlkfj skdfj a' for i 14
String '15' is 'sdjfklsaj df' for i 15
String '16' is 'asdf sjakldfj ' for i 16
String '17' is 'asdjfkasjlfjsald ' for i 17
String '18' is 'asdflkjsdf  asldkjf ' for i 18
String '19' is 'askldfjas ldflk' for i 19
[1]    58751 segmentation fault  ./a.out < test

Any input is appreciated!

coderman
  • 59
  • 6
  • 2
    `instructionArray = (char **)realloc(` only updates the local copy of instructionArray , not the one in main. if the array has to be moved, the value of instructionArray in main will be invalid. – Avi Berger Oct 04 '22 at 07:02
  • The output shown does not match the code shown... "... for i..." v. "... for count..." – Fe2O3 Oct 04 '22 at 07:08
  • 2
    And, clobbering the same '\n' twice (in the "windows" version) won't remove the '\r' that you are trying to clobber... – Fe2O3 Oct 04 '22 at 07:12

0 Answers0