-3

I'm working on a project and I keep getting segmentation faults, and the values of the structs aren't being passed. Figuring out why is driving my crazy. I've tried figuring out the problem with simpler programs, and I think I've found the problem, but I'm not sure how to fix it.

The problem is that when I "malloc" a struct, THEN pass by value, the value is lost. Adding "free" later produces a segmentation fault. I'm not trying to access a value from before the "malloc()" or after the "free()", so I'm confused as to why this is happening.

Here's a simple model of the problem:

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

    struct structexample
    {
        int element;
    };

    void initStruct(struct structexample * teststruct, int * number)
    {
        teststruct = malloc(sizeof(struct structexample)); 
        teststruct->element = 10;
        printf("teststruct element is %d in initStruct\n", teststruct->element);
        *number = 5;
    }

    void printtest(struct structexample * teststruct, int * number)
    {
        printf("teststruct element is %d in printtest\n", teststruct->element);
        printf("Number is %d\n", *number);
        free(teststruct);
    }

int main()
{
    int number;
    struct structexample teststruct;
    initStruct(&teststruct, &number);
    printtest(&teststruct, &number);
    printf("teststruct element is %d in main()", teststruct.element);
    return 0;
}

This produces:

teststruct element is 10 in initStruct
teststruct element is -7967792 in printtest
Number is 5
Segmentation fault

I compile the program with "gcc -Wall -pedantic -ansi" and get no errors or warnings there.

When I comment out "malloc" and "free" it correctly produces:

teststruct element is 10 in initStruct
teststruct element is 10 in printtest
Number is 5

If I only comment out "free" but leave "malloc" in, that fixes the segmentation fault, but the values of the structs are still incorrect. In this simple program I don't really need "malloc()" and "free()", but I do need them in my larger project. If I can make them work in this simpler program, then I think I can fix the larger one. I can't find a similar problem on Google unfortunately.

BSMP
  • 4,596
  • 8
  • 33
  • 44
  • 1
    Ansi C is obsolete. Use C99 or C11. Compile with all warnings & debug info (`gcc -Wall -Wextra -g` and perhaps `-std=c99`). If on Linux, learn about [valgrind](http://valgrind.org/) and use `gdb` (it has watchpoints). – Basile Starynkevitch Feb 29 '16 at 18:17

3 Answers3

1

You are mixing stack and heap

void initStruct(struct structexample * teststruct, int * number)
 {
     teststruct = malloc(sizeof(struct structexample)); 
     ^ There is no need to use malloc, teststruct is on the stack

 ...

int main()
{
    int number;
    struct structexample teststruct;
    initStruct(&teststruct, &number);
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
  • Thanks! I'm having another problem, which I've added to this question with an edit. Could you please help me with this too? – user5988698 Feb 29 '16 at 23:41
1

Just remove the free() line from printtest() so it looks like this:

void printtest(struct structexample * teststruct, int * number)
{
    printf("teststruct element is %d in printtest\n", teststruct->element);
    printf("Number is %d\n", *number);
}

The segmentation fault happens because you're trying to free memory that is on the stack !!

You can also remove the malloc() line from initStruct() because it has no use: it's allocating space for a struct structexample and returning it's address into teststruct wich is a struct structexample * allocated on the heap and passed to initStruct(), meaning it will be lost once the call to initStruct() returns.

Mohamed
  • 11
  • 3
  • Thanks! I'm having another problem, which I've added to this question with an edit. Could you please help me with this too? – user5988698 Feb 29 '16 at 23:40
  • If it's reading white space separated words you want, use `fscanf()`, it does that. test for the end of file using `feof()` in a `while` loop to read words using `fscanf()`. – Mohamed Mar 01 '16 at 10:59
0
void initStruct(struct structexample * teststruct, int * number)
{
    teststruct = malloc(sizeof(struct structexample)); 
    teststruct->element = 10;
    printf("teststruct element is %d in initStruct\n", teststruct->element);
    *number = 5;
}

You pass this function a value, the address of a structure, which it totally ignores. It allocates with malloc, but does nothing with the address it got back. It doesn't return it. It doesn't put it anywhere other code can get it. So you've just leaked this object.

void printtest(struct structexample * teststruct, int * number)
{
    printf("teststruct element is %d in printtest\n", teststruct->element);
    printf("Number is %d\n", *number);
    free(teststruct);
}

So printtest passes teststruct to free, so it should be passed a value returned from malloc.

struct structexample teststruct;
initStruct(&teststruct, &number);
printtest(&teststruct, &number);

But you pass printtest the address of teststruct, which is allocated on the stack. That can't be right.

Are you expecting initStruct to somehow move teststruct? It surely can't do that.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Ah I think I get it now. "Malloc" changes where the pointer to "teststruct" points to, which is a different one than the one passed into the function. I'm confused about where I should malloc now though. I've written "&teststruct = malloc(sizeof(struct structexample));" outside the function, but that produces the error " lvalue required as left operand of assignment". – user5988698 Feb 29 '16 at 18:54
  • How about `struct structexample* teststruct = malloc ...`? – David Schwartz Feb 29 '16 at 18:56
  • I have to split it up into two lines because I can't mix declarations and code, but that works! Thanks. – user5988698 Feb 29 '16 at 19:14
  • I'm having another problem I'm having trouble with. I've added it to this question with an edit. Could you please help me with this? – user5988698 Feb 29 '16 at 23:33
  • What do you think `sizeof(*fp)` does? I think you have a serious misunderstanding about what `sizeof` does. Either that or you don't understand what a `FILE` is -- it's the thing that you use to access an opened file. Since `*fp` is a `FILE`, then `sizeof(*fp)` is saying "how big is this thing that I'm using to access this opened file". What does that have to do with anything? – David Schwartz Feb 29 '16 at 23:41
  • I meant for "data" to be the size of the data stored in "fp". I thought a FILE acted like a pointer to a file, so I dereferenced fp in "sizeof()" to attempt to refer to the size of the contents. – user5988698 Mar 01 '16 at 00:02
  • I just read this: http://stackoverflow.com/questions/238603/how-can-i-get-a-files-size-in-c I'm going to try adding that in to see if it works. – user5988698 Mar 01 '16 at 00:13
  • @user5988698 Then you have some misunderstandings about how C types work. The size of something is always a function of its type and always independent of its contents. – David Schwartz Mar 01 '16 at 00:20
  • Thanks! I think I've fixed problem, but I'm still having the other problems I mentioned. I've updated my post with a second edit. – user5988698 Mar 01 '16 at 00:30
  • I don't mean to be rude, but it sounds like you just need to learn C and should probably work on simpler problems so that you don't have to figure out 100 things at once. – David Schwartz Mar 01 '16 at 00:33
  • Thanks for the honest feedback, but I'm learning C as part of a course, so I don't really have a choice! – user5988698 Mar 01 '16 at 00:36
  • I'm still trying to figure this out. Are there any tips or hints you could give me to help me out? – user5988698 Mar 01 '16 at 00:48