1. Not finding help here? Sign up for a free 30min tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Pointers and Structs in C

  1. Nov 6, 2011 #1
    Hello all,

    I am experiencing some odd output behavior from a program that I am working on:

    Header file

    Code (Text):
    #include <pthread.h>

    struct ringbuf_t
    {
      pthread_mutex_t mutex;
      pthread_cond_t cond_full;
      pthread_cond_t cond_empty;
      int bufsiz;
      int front;
      int back;
      char* buf;
    };

    extern struct ringbuf_t* rb_init (int bufsiz);

    extern void rb_finalize (struct ringbuf_t* rb);

    extern int rb_size (struct ringbuf_t* rb);

    extern int rb_is_full (struct ringbuf_t* rb);

    extern int rb_is_empty (struct ringbuf_t* rb);

    extern void rb_insert (struct ringbuf_t* rb, int c);

    extern int rb_remove (struct ringbuf_t* rb);
    First source file

    Code (Text):
    #include "ringbuf.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <string.h>

    struct ringbuf_t* rb_init(int bufsiz)
    {
      int x;
      char *temp = malloc(sizeof(char) * bufsiz);
      memset(temp, '\0', sizeof(temp));

      //temp[bufsiz-2] = 'w';

      struct ringbuf_t newrb = { PTHREAD_MUTEX_INITIALIZER,
                     PTHREAD_COND_INITIALIZER,
                     PTHREAD_COND_INITIALIZER,
                     bufsiz, 0, bufsiz - 1, temp };

      struct ringbuf_t* p = malloc(sizeof(struct ringbuf_t));
      p = &newrb;

      return p;
    }

    void rb_finalize(struct ringbuf_t* rb)
    {
      free(rb);
    }

    int rb_size(struct ringbuf_t* rb)
    {
      int x;
     
      for (x = 0; rb->buf[x] != '\0'; x++)
        ;

      return x;
    }

    int rb_is_full(struct ringbuf_t* rb)
    {
      if (rb->buf[rb->back] != '\0')
        return 1;

      return 0;
    }

    int rb_is_empty(struct ringbuf_t* rb)
    {
      if (rb->buf[rb->front] != '\0')
        return 0;

      return 1;
    }
     
    Main source file
    Code (Text):

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

    int main()
    {
      printf("\nTesting first method...");
      struct ringbuf_t *p = malloc(sizeof(struct ringbuf_t));
      p = rb_init(10);

      printf("\n%d", p->bufsiz);
      printf("\n%d", p->bufsiz);

      return 0;
    }
     
    I have been using the main method to test stuff out, and currently am experiencing some odd behavior, which I think may have to do with how I am allocating memory or using pointers, I am not sure. Basically, the first time I reference anything within the created struct (in this test I referenced bufsiz), it reports the correct value the first time, and then gives junk every time afterward. Same thing for function calls or a combination of both, as if the data is only available initially and then is immediately lost as soon as it gets accessed once.

    Is there something off in my code that is causing this?

    Thank you in advance.
     
  2. jcsd
  3. Nov 6, 2011 #2

    Mark44

    Staff: Mentor

    In main, you allocate a block of memory for a ring buffer, and then call rb_init, which also allocates a block of memory. You shouldn't need to do this twice.
     
  4. Nov 6, 2011 #3
    Fair enough, but even implementing that fix causes the problem to persist.
     
  5. Nov 6, 2011 #4

    I like Serena

    User Avatar
    Homework Helper

    Try:
    *p = newrb;
    instead of
    p = &newrb;

    That is, you need to copy the contents that is pointed to, and not the pointer itself.
     
  6. Nov 6, 2011 #5
    Ooh, I think that fixed it! Thank you so much. Now hopefully I can actually get to the multi-threading part and actually get to the intended practice. :P
     
  7. Nov 6, 2011 #6

    I like Serena

    User Avatar
    Homework Helper

    Just so you know, you should also use:
    memset(temp, '\0', sizeof(char) * bufsiz);

    instead of:
    memset(temp, '\0', sizeof(temp));

    Otherwise, you only set the first 4 bytes (which is the size of a pointer) of your buffer to zero .
     
  8. Nov 6, 2011 #7
    Will do. Thanks. Playing around with pointers and memory seems to be my stumbling block in C.
     
  9. Nov 7, 2011 #8

    Mark44

    Staff: Mentor

    In case it's not obvious why p = &newrb; isn't working for you, here's an explanation.

    In main, p is set to the address of a ring buffer struct whose memory has been allocated from the heap. All is good.

    In rb_init, a local variable named newrb is created. This struct is allocated on the stack. Just before rb_init exits, p is set to the address of newrb. Note that stack variables cease to exist outside the function in which they are declared. In practical terms, this means that whatever was at that location during the function's life can be used for other purposes after the function exits.

    Back in main, p is pointing to a location on the stack that no longer holds what was stored in newrb.
     
  10. Nov 7, 2011 #9
    Ah-ha. I figured it was something like that based on the behavior. Thank you Mark.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Pointers and Structs in C
Loading...