问题
I am learning C and trying to make a function that would create an array of arrays of strings.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void parse(char ***aoa)
{
char *string = calloc(9, sizeof(char));        //create a string of size 8+1
strcpy(string, "hi world");                   // put text in that array
char **array = calloc(10, sizeof(char *));    //create an array of strings
aoa = calloc(10, sizeof(char *));             //create and array of arrays
aoa[0] = array;                               //assign string array to the 0th elements of new array
array[0] = string;                            //assign our string to 0th element of string carry
printf("%s\n", aoa[0][0]);                    //print 0th element of 0th array. 
}
int main()
{
char ***array = NULL;
parse(array);
printf("%s\n", array[0][0]);
return 1;
}
The aoa (array of arrays) is on the heap so it should be the same for both methods. It does print "hi world" in the parse function, but gives Segmentation Fault in main, what is the problem with my code?
Obviously I need to free() everything and do error checking, but I removed it to show the gist of the problem
回答1:
You reserve space for a local variable in parse(), you need to pass a pointer to array from main and then dereference inside the function:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void parse(char ****aoa)
{
    char *string = calloc(9, sizeof(char));        //create a string of size 8+1
    strcpy(string, "hi world");                   // put text in that array
    char **array = calloc(10, sizeof(char *));    //create an array of strings
    *aoa = calloc(10, sizeof(char *));             //create and array of arrays
    *(aoa[0]) = array;                               //assign string array to the 0th elements of new array
    array[0] = string;                            //assign our string to 0th element of string carry
    printf("%s\n", *(aoa[0][0]));                    //print 0th element of 0th array. 
}
int main()
{
    char ***array = NULL;
    parse(&array);
    printf("%s\n", array[0][0]);
    return 1;
}
    回答2:
The problem tragically lies in your main. You send your variable array to the parse function as a value, hence, it is not changed by parse and stays NULL in the MAIN. The prototype of your function parse should be
void parse(char ****aoa)
and you should send it to the main like this :
parse(&array)
But you are overcomplicating the code. Try to initiate your array of arrays elsewhere instead of passing a pointer to it in the function. for example :
char ***getArray(void)
{
char ***ret;                                   //the array you return
char *string = calloc(9, sizeof(char));        //create a string of size 8+1
strcpy(string, "hi world");                   // put text in that array
char **array = calloc(10, sizeof(char **));    //create an array of strings
ret = calloc(10, sizeof(char ***));             //create and array of arrays
ret[0] = array;                               //assign string array to the 0th elements of new array
array[0] = string;                            //assign our string to 0th element of string carry
return (ret);
}
int main()
{
char ***array = getArray();
printf("%s\n", array[0][0]);
return (0);
}
And by the way, always verify that your allocations did not fail.
回答3:
There is a sound rule of thumb saying that if you ever find yourself in need of more than two levels of indirection, then your program design is bad. ("Three star programming")
You are also using pointer-based lookup-tables rather than arrays. This causes segmentation and prevents you to regard the allocated result as a chunk of contiguous memory.
On top of that, your code has several other issues. I would consider rewriting it from scratch and actually use multi-dimensional arrays instead. Here is a working example:
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
bool create_string_array2d (size_t x, 
                            size_t y, 
                            size_t max_length, 
                            char (**string_array)[x][y][max_length]);
void print_string_array2d (size_t x,
                           size_t y,
                           size_t max_length,
                           char string_array[x][y][max_length]);
static void fill_with_junk (size_t x,
                            size_t y,
                            size_t max_length,
                            char string_array[x][y][max_length]);
int main()
{
  const size_t X = 9;
  const size_t Y = 10;
  const size_t MAX_CHARS = sizeof("hi world xx yy");
  char (*array)[X][Y][MAX_CHARS];
  bool result;
  result = create_string_array2d(X, Y, MAX_CHARS, &array);
  if(result == false)
  {
    printf("out of memory, halt & catch fire");
    return 0;
  }
  fill_with_junk(X, Y, MAX_CHARS, *array);
  print_string_array2d(X, Y, MAX_CHARS, *array);
  free(array);
  return 0;
}
bool create_string_array2d (size_t x, 
                            size_t y, 
                            size_t max_length, 
                            char (**string_array)[x][y][max_length])
{
  *string_array = calloc(1, sizeof(char[x][y][max_length]));
  return string_array != NULL;
}
void print_string_array2d (size_t x,
                           size_t y,
                           size_t max_length,
                           char string_array[x][y][max_length])
{
  for(size_t i=0; i<x; i++)
  {
    for(size_t j=0; j<y; j++)
    {
      printf("%s\n", string_array[i][j] );
    }
    printf("\n");
  }
}
static void fill_with_junk (size_t x,
                            size_t y,
                            size_t max_length,
                            char string_array [x][y][max_length])
{
  for(size_t i=0; i<x; i++)
  {
    for(size_t j=0; j<y; j++)
    {
      char junk [sizeof("hi world xx yy ")] = "hi world ";
      char num  [sizeof("xx ")];
      sprintf(num, "%.2d ", (int)i);
      strcat(junk, num);
      sprintf(num, "%.2d", (int)j);
      strcat(junk, num);
      strcpy(string_array[i][j], junk);
    }
  }
}
    回答4:
You never dereference aoa inside the function, so you just overwrite the argument's local value. Function arguments are passed by value in C. You also shouldn't need to alllocate two string arrays, that doesn't seem right.
来源:https://stackoverflow.com/questions/35310798/multidimensional-array-on-the-heap-c