1

I am trying to write data into a variable length two dimensional array and my program keeps seg-faulting when I call myfunc but it works fine when I try to perform the same manipulation outside of a function. I can tell that the issues is that the address pointed to at array[0] doesn't equal the address pointed to at data[0]. Can someone advise me as to the root cause of this issue and proper way to rewrite myfun.

void myfun(unsigned char **array){
    printf("array = %p, array[0] = %p\n", array, array[0]);
    //This line below causes a segfault
    strcpy(array[0], "Position0");
}

int main(void) {
    int row = rand() % 5 + 1;   // random number between 1-5
    int col = rand() % 10 + 20;   // random number between 20-29
    unsigned char data[row][col];

    printf("data = %p, data[0] = %p\n", data, data[0]);

    //This function call causes a segfault
    myfun(data);
    printf("%s\n", data[0]);

    //This works
    strcpy(data[1], "Position1");
    printf("%s\n", data[1]);

    return 0;
}
jprince14
  • 191
  • 2
  • 13
  • In your text you say you get a segfault when you perform the operation inside `myfun`, but not when you perform it outside the function; the comment in your code says the opposite. – Beta Feb 09 '16 at 04:38
  • I just updated the comments in the code to be more clear. The line that causes the segfault is "strcpy(array[0], "Position0");" – jprince14 Feb 09 '16 at 04:43
  • 1
    Your compiler should have warned you that `char[x][y]` is incompatible with`char**`, and you should have listened to that warning, because it's true. If it didn't warn you, learn how to enable warnings. – n. m. could be an AI Feb 09 '16 at 05:06
  • Possible duplicate of [Is 2d array a double pointer?](http://stackoverflow.com/questions/7586702/is-2d-array-a-double-pointer) – n. m. could be an AI Feb 09 '16 at 05:07

2 Answers2

3

Since you are clearly using C99 or later and a compiler with VLA (variable length array) support, you can write the function correctly quite easily:

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

static void myfun(int rows, int cols, char array[rows][cols])
{
    printf("array = %p, array[0] = %p\n", array, array[0]);
    strcpy(array[0], "Position0");
    printf("a[0] = [%s]\n", array[0]);
}

int main(void)
{
    int row = rand() % 5 + 1;   // random number between 1-5
    int col = rand() % 10 + 20;   // random number between 20-29
    unsigned char data[row][col];

    printf("data = %p, data[0] = %p\n", data, data[0]);

    myfun(row, col, data);
    printf("%s\n", data[0]);

    strcpy(data[1], "Position1");
    printf("%s\n", data[1]);

    return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

The problem is the function definition. If you want to pass a matrix the way you did, you have to allocate it dynamically, but that's another story. I'll explain the error.

The C language actually implement the static matrices as a single array of size row*col. That is for efficiency.

When you pass the static matrix to that function, you got a problem: it expects a double pointer, but what you pass is actually a single pointer requiring the number of columns. You have to write like this:

void myfun(unsigned char array[][col]){ ...

That's how you should define it, where col is the number of columns.

The problem's that you don't know the number of columns, it's variable, so I suggest you use malloc or calloc to alocate a dynamic matrix.

Editing: look at this link posted as comment by n.m. for details on the static matrix that C implements: Is 2d array a double pointer?

Community
  • 1
  • 1
  • 2
    With C99 or C11 and VLA (variable-length array) support, you can handle it cleanly without needing dynamic memory allocation. – Jonathan Leffler Feb 09 '16 at 06:22
  • 1
    I like the malloc method: I got it working with the following code: `data2 = (unsigned char**)malloc(row * col); myfun_malloc(data2); 'void myfun_malloc(char** array) { printf("In myfun_malloc: array = %p, array[2] = %p\n", array, (array + (2 * sizeof(char*))) ); strcpy(array + (2 * sizeof(char*)), "Position2"); printf("a[2] = [%s]\n", (array + (2 * sizeof(char*))) ); }` – jprince14 Feb 09 '16 at 13:05
  • I also would rather using the dynamic rather than semi-dynamic solution, in this specific case. Nevertheless, I appreciate the feedback on the VLA. It's important to know the difference in efficiency of using semi-dynamic allocated arrays. – Judismar Arpini Junior Feb 09 '16 at 15:13