3

I made a function that returns a pointer to a newly created matrix. Now I want this function to return an error code of type status_t instead of the pointer. To do this, another pointer level has to be added and the matrix has to be returned by reference. However, I can't understand why a segmentation error appears. Here is part of my working code (a) and my failed attempt (b):

(a)

int **create_matrix(size_t dimension) {
    int **p;
    size_t e;
    size_t h;

    if (dimension == 0)
        return NULL;

    for (h = 0; h < dimension; ++h) {
        if ((p[h] = malloc(dimension * sizeof(int))) == NULL) { 
            for (e = h; e >= 0; --e) {  
                free(p[e]);
                p[e] = NULL;
            } <-------- missing closing brace
            return NULL;
        }
    }
    return p;
}

(b)

status_t create_matrix(size_t dimension, int ***p) {
    size_t e;
    size_t h;

    if (p == NULL)
        return ERROR_NULL_POINTER;

    for (h = 0; h < dimension; ++h) {
        if (((*p)[h] = malloc(dimension * sizeof(int))) == NULL) { 
            for (e = h; e >= 0; --e) {  
                free((*p)[e]);
                (*p)[e] = NULL;
            } <-------- missing closing brace
            return ERROR_NO_MEMORY;
        }
    }
}

thanks!

2
  • Why are you calling free() when you create a matrix? Commented Jun 6, 2019 at 20:44
  • If malloc fails no there will be memory leaks. I'm trying to avoid this Commented Jun 6, 2019 at 21:12

1 Answer 1

3

(a) isn't exactly "working":

For one thing, it has more { than }, so it doesn't even compile. You probably forgot to terminate your outer for loop.

int ** p;
...
    if ((p[h]=...))

This dereferences p before it was initialized. Using the value of an uninitialized variable is undefined behavior. You need to assign something to p before you use it (probably by dynamically allocating another array).

To determine whether version (b) has the same issue, we'd have to see the calling code, but at a guess it's also UB.

There's another problem in the inner loop:

        for (e = h; e >= 0; --e)

e is a size_t, which is an unsigned integer type, so the condition e >= 0 is always true.

What compiler (and compiler options) are you using? With gcc -Wall -Wextra -pedantic I get warnings for both of these.

A fixed version would look like this:

int **create_matrix(size_t dimension) {
    int **p = calloc(dimension, sizeof *p);
    if (!p) {
        return NULL;
    }

    for (size_t i = 0; i < dimension; i++) {
        if (!(p[i] = calloc(dimension, sizeof *p[i]))) {
            while (i--) {
                free(p[i]);
            }
            free(p);
            return NULL;
        }
    }

    return p;
}

Version (b) can then be defined as

status_t create_matrix_2(size_t dimension, int ***p) {
    if (!p) {
        return ERROR_NULL_POINTER;
    }
    if (!(*p = create_matrix(dimension))) {
        return ERROR_NO_MEMORY;
    }
    return SUCCESS_OR_SOMETHING;
}

I'm not sure what you want to return for success; your version (b) is missing a return statement there.

Sign up to request clarification or add additional context in comments.

3 Comments

you're correct, *p[e] was a typo when typing this post, will edit. I'm using gcc version 7.4.0 with flags -ansi -pedantic -Wall. I don't understand what you mean by saying p is de-referenced before initialization, how should I adress this? Thanks
@JuanHirschmann See my fixed version. You need to assign a value to p before you can use the value of p. What is unclear about this?
@JuanHirschmann I've removed the *p[e] part of my answer, but I've found another issue: e >= 0 is always true.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.