-2

I am having the next problem. I'm trying to create a dynamic matrix of strings which dimensions are defined by the user. The next code I made returns a segmentation fault:

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

int main(){
    char ***pa = NULL;
    int rows, columns , max, i, j = 0;

    //Ask dimension
    puts("Type number of columns: ");
    scanf("%d",&columns);
    puts("Type number of rows: ");
    scanf("%d",&rows);
    puts("Type max string length: ");
    scanf("%d",&max);

    //Allocate in memory
    ***pa = (char ***)malloc(rows * sizeof(char**));
    for(i=0;i<rows; i++){
        pa[i] = (char **)malloc(columns * sizeof(char*));
        for(j=0; i<columns;j++){
            pa[i][j] = (char)malloc((max+1)*sizeof(char));
        }
    }
    puts("Memory OK");

    //Fill the matrix
    i = 0;
    j = 0;
    for(i=0;i<rows;i++){
        strncpy(pa[i][j] , "Hello world", max);
        for(j=0;j<columns;j++){
            strncpy(pa[i][j] , "Hello world", max); 
        }
    }

    //Shows the matrix
    for(i=0;i<rows;i++){
        puts(pa[i][j]);
        for(j=0;j<columns;j++){
            puts(pa[i][j]);
        }
    }
    //Cleans the matrix
    free(pa);

    return 0;
}

I know I should check if the returned pointer by malloc is NULL but I didn't included it yet. The program does not print this so the problem is in the malloc for's

puts("Memory OK");

How can I debug this so I could know what happend? Did I made a mistake while coding it?

3 Answers3

1

I'd recommend you leverage c99 to the fullest, and allocate the entire matrix as a single block. You'll be reducing the fragmentation of your programs memory and making iteration over the matrix more cache friendly:

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

int main(void) {

    int rows, columns , max;

    puts("Type number of columns: ");
    scanf("%d",&columns);
    puts("Type number of rows: ");
    scanf("%d",&rows);
    puts("Type max string length: ");
    scanf("%d",&max);

    char (*mat)[columns][max+1] = malloc(rows * columns * (max + 1));

    for(int i = 0; i < rows; ++i){
        for(int j = 0; j < columns; ++j) {
            strncpy(mat[i][j] , "Hello world", max); 
        }
    }

    for(int i = 0; i < rows; ++i){
        for(int j = 0; j < columns; ++j){
            puts(mat[i][j]);
        }
    }

    free(mat);

    return 0;
}

Other added bonii:

  1. Removes the complexity involved with allocating your memory. No more nested loops with mallocs

  2. No need to loop for freeing the whole thing, just free the one pointer. You already do that, but in your case it leaks memory.

Cons:

  1. May fail to allocate the entire block for large matrices. Here the fragmented approach may be better.
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
0

Change

pa[i][j] = (char)malloc((max+1)*sizeof(char));

into:

pa[i][j] = (char *)malloc((max+1)*sizeof(char));

Also, no need for the outer (first) strncpy in the main.

[EDIT]

Also, the first allocation line ***pa = ... should be pa = .... You want to assign an address to the pointer pa, not de-reference it (***pa de-references the pointer pa that has not been yet initialized).

AhmadWabbi
  • 2,253
  • 1
  • 20
  • 35
0

Thanks to veryone for helping me to solve it. I've learned new things with you. First of all, I changed this.

pa = malloc(rows * sizeof(char**));
for(i=0;i<rows; i++){
    pa[i] = malloc(columns * sizeof(char*));
    for(j=0; j<columns;j++){//Here there was an i. That was totally wrong.
        pa[i][j] = malloc((max+1)*sizeof(char));
    }
}

Now it works and allocates correctly the matrix into de memory.

  • So, you did what I suggested in my answer, but without the casting (even though you may have kept it). In SO, this is usually translated to an up-vote, as an expression of gratitude for those who spent time helping you. I am telling you this just because you are new here, no need to your up-vote anyway. – AhmadWabbi Nov 15 '16 at 21:58
  • As you say I just registered in the page, Im still learning how this works. Excuse me if I made a mistake. – Carlos Manrique Enguita Nov 15 '16 at 22:08
  • No problem, I knew that. I just wanted to draw your attention to it so that the others do not take it bad in the future. Good luck. – AhmadWabbi Nov 15 '16 at 22:31