0

(Proficient at C++, newbie at C) getting a segfault error from the addArray() call in main(). I've checked many posts and several texts, it compiles, but no luck running it. I'm coding it on VS2015 and all the usual handy cues are there with pointers, etc. Cleary something I'm not aware of or a syntax error. This is the distilled code that reproduces the error.

#include<stdio.h>
#include <stdlib.h>
#define TYPE int

struct arrayHolder {
    TYPE data[100];
    int count;
};

//prototypes.
void initArray(struct arrayHolder * );
void addArray(struct arrayHolder *, TYPE);


int main() {
    struct arrayHolder * myStruct = NULL;
    initArray(myStruct);
    addArray(myStruct, 123);
}

/* Allocate memory for struct arrayHolder */
void initArray(struct arrayHolder * b) {
    b = (struct arrayHolder *)malloc(sizeof(struct arrayHolder));
    b->count = 0;
}


/* Add an element to data[] */
void addArray(struct arrayHolder * b, TYPE v) {
    int count = b->count;
    b->data[count] = v;
    (b->count)++;
}
5
  • 2
    Arguments are passed by value. The assignment within initArray() does not have effect outside the function. Commented Apr 6, 2016 at 19:10
  • @def1: But aren't I passing a pointer? Commented Apr 6, 2016 at 19:12
  • @ Chris: Yes, and you can change the data the pointer points to, but you assign a new value to the pointer itself which will not carry over outside the function, use a pointer to the pointer. Commented Apr 6, 2016 at 19:17
  • 1
    Standard note: Don't cast void * to other pointers in C. Commented Apr 6, 2016 at 19:18
  • 1
    A syntax error will not cause a segfault, simply because it will not compile. And your code would be wrong in C++, too. Commented Apr 6, 2016 at 19:19

2 Answers 2

2

As @def1 observed, you are passing pointers by value. That's not an issue for addArray() -- the problem is with initArray(). That function's parameter is local to the function, so when you assign the malloc()ed pointer to it, the result is not visible in main(). Ultimately, you end up passing a NULL pointer to addArray().

There are at least two possible solutions.

  1. In the code presented, it's not clear to me why the struct arrayholder needs to be dynamically allocated at all. If in main() you declare instead struct arrayholder myStruct; and remove the malloc() call from initArray(), then everything else should work as-is.

  2. Alternatively, if you do need to perform dynamic allocation then either you should return a pointer to the allocated memory from initArray() (in which case that function does not require a parameter) or else you need to pass a double pointer to the function, so that main()'s pointer can be updated thereby.

The only one of those alternatives that should be at all tricky is the double pointer variant, which would look like this:

int main() {
    struct arrayHolder * myStruct = NULL;
    initArray(&myStruct);                 /* difference here */
    addArray(myStruct, 123);
}

/* Allocate memory for struct arrayHolder */
void initArray(struct arrayHolder ** b) {
    /* no cast is required here in C, and many account one poor style: */:
    *b = malloc(sizeof(struct arrayHolder));
    (*b)->count = 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

@Chris, I'm glad to help. As Olaf observed, however, your code was not correct in C++, either. All of my comments apply there as well, except about removing the cast of malloc()'s return value. C++ requires that cast.
@Chris: It is not different from passing pointers in C++. You just have the option to use a reference to the pointer, but that is a different type and has a distinct syntax.
1
void initArray(struct arrayHolder * b) 

Here you pass a pointer to a struct arrayHolder to the function. The pointer is passed by value which means it is a copy. You can change the data the pointer is pointing to but when you assign the result of malloc to b you are modifying the copy of the pointer itself, which will not influence the pointer in main.

Possible solution is to use a pointer to a pointer.

void initArray(struct arrayHolder ** b) {
    *b = (struct arrayHolder *)malloc(sizeof(struct arrayHolder));
    (*b)->count = 0;
}

Comments

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.