Michael Hackman
Michael Hackman

Reputation: 573

Segmentation fault upon reading from an array

I wrote a small program to illustrate a problem I'm running into. This program should copy the contents of "buff[200]" into the first position of the array "output". After performing the copy, I read the value out several times to see when it vanishes as I get a segmentation fault as soon as I try to access the data outside of the scope of driverFunc. I'm aware that I'm creating an array with 6 positions in it but only adding data to the first position, this will eventually be inside a loop that populates the rest of the output array. I also have the requirement for my use case that I need to be able to expand the size of this array.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 1035
int driverFunc(char ** output, int * sizeOfOutput) {
  int rows = 5;
  char buff[200] = "hello world";

  output = malloc(rows * sizeof(char *));  //malloc row space
  //malloc column space
  for (int i = 0; i < rows; i ++) {
    output[i] = malloc(BUFFER_SIZE * sizeof(char));
  }

  //copy contents of buff into first position of output
  strncpy(output[0], buff, BUFFER_SIZE-1);
  printf("Output 1: %s\n", output[0]); //verify that it's there

  //resize the array
  output = realloc(output, (rows+1) * sizeof(char *));
  //allocate space for the new entry
  output[rows] = malloc(BUFFER_SIZE * sizeof(char));
  *sizeOfOutput = rows;

  //verify that it's still there
  printf("Output 2: %s\n", output[0]);
  return 0;
}
int main() {
  char ** outputs;
  int sizeOfOutput;
  driverFunc(outputs, &sizeOfOutput);
  //verify that we can do useful things with our output
  printf("Reported size: %d\n", sizeOfOutput);
  printf("Captured output: %s\n", outputs[0]);  //segfault
}

expected output:

Output 1: hello world
Output 2: hello world
Reported size: 5
Captured output: hello world

received output:

Output 1: hello world
Output 2: hello world
Reported size: 5
Segmentation fault (core dumped)

Upvotes: 1

Views: 479

Answers (2)

Vlad from Moscow
Vlad from Moscow

Reputation: 310990

If you are going to change the value of the pointer outputs declared in main

char ** outputs;

in a function then the function should except the pointer by reference that is indirectly through pointer.

Thus the function should be declared at least like

int driverFunc(char *** output, int * sizeOfOutput);

and called like

driverFunc( &outputs, &sizeOfOutput);

Using the function strncpy

strncpy(output[0], buff, BUFFER_SIZE-1);

does not make great sense. It is simpler to use strcpy

strcpy( output[0], buff );

In case if the reallocation fails

 output = realloc(output, (rows+1) * sizeof(char *));

the previous value of the pointer output will be lost. So you need to use an intermediate variable to reallocate the memory and check whether its value after the call is equal to NULL or not.

The variable sizeOfOutput should be set to

*sizeOfOutput = rows + 1;

In main you should free all allocated memory in the function.

Upvotes: 1

Piotr Praszmo
Piotr Praszmo

Reputation: 18320

You are passing outputs into driverFunc as a value:

driverFunc(outputs, &sizeOfOutput);

its value will be passed to function but not returned. So, when you use it in:

printf("Captured output: %s\n", outputs[0]);

outputs is still uninitialized.

You need to pass it as a reference (and change driverFunc accordingly):

driverFunc(&outputs, &sizeOfOutput);

or just return it:

outputs = driverFunc(&sizeOfOutput);

Upvotes: 1

Related Questions