#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2010
    Posts
    49
    Rep Power
    15

    Exclamation Passing around global structures


    Ohai there. I've been trying to figure out how to implement global structures in C...

    My following code seems sound to me, but I get a SIGSEGV (segmentation fault) whenever I run it.

    My buggy code is this:
    [CODE=C]
    #include<stdio.h>
    #include<stdlib.h>

    typedef struct{
    char* d;
    } t;

    void* __t (void){
    static t* s;
    char* c = "foo";
    s->d = malloc (sizeof (c));
    s->d = c;
    return &s;
    }

    void __k (volatile unsigned int* p){
    t* s;
    char* c = :asdf";
    s = (t*)p;
    free (s->d);
    s->d = malloc (sizeof (c));
    s->d = c;
    }

    int main (void){
    volatile unsigned int* ptr == __t ();
    __k (p);

    t* s;
    s = (t*)p;
    printf ("%s", s->d);

    return 0;
    }
    [/CODE]

    I would like to know WHY this code doesn't work, and HOW to fix it. I don't believe it is my machine's arch or GCC version, as the following code works:

    [CODE=c]
    #include<stdio.h>

    void c (volatile unsigned int* p){
    char* k;
    k = (char*)p;
    *k = "foo";
    }

    int main (void){
    char* k = "cat";
    c (&k);

    printf ("%s", k);
    return 0;
    }
    [/CODE]

    Thank you :D
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,172
    Rep Power
    2222
    It is not at all clear what you are trying to do, which isn't helped by some odd statements:
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    
    typedef struct{
      char* d;
    } t;
    
    void* __t (void){
      static t* s;
      char* c = "foo";
      s->d = malloc (sizeof (c));  // s is an uninitialized pointer
      s->d = c;     // this misuse of s is probably the direct reason for the SEGFAULT
      return &s;
    }
    
    void __k (volatile unsigned int* p){
      t* s;
      char* c = :asdf";  // for me, this is a completely novel use of the colon; I'm very surprised it compiled 
      s = (t*)p;
      free (s->d);
      s->d = malloc (sizeof (c));
      s->d = c;
    }
    
    int main (void){
      volatile unsigned int* ptr == __t ();  // what is that equality test doing in a declaration? 
      __k (p);  // what is p?  It's undeclared.  How did this compile without warnings?
      
      t* s;
      s = (t*)p;  // p is undeclared and uninitialized, so contains garbage.  Acts the same as an uninitialized pointer
      printf ("%s", s->d);
    
      return 0;
    }
    If you are not asking for warnings or are ignoring warnings, then stop that! Always ask for warnings (at the very least always compile with -Wall) and never ignore warnings. Warnings are more important than error messages.
    Last edited by dwise1_aol; December 13th, 2012 at 12:00 AM.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2010
    Posts
    49
    Rep Power
    15
    Thank you for "annotating" my code and pointing things out. I typed
    this up rather late last night and who knows what I'm gonna think
    about it now :)

    [CODE=c]
    #include<stdio.h>
    #include<stdlib.h>

    typedef struct{
    char* d;
    } t;

    void* __t (void){
    static t* s;
    char* c = "foo";
    s->d = malloc (sizeof (c)); // (s is an uninitialized pointer) How
    would I initialize it correctly then?
    s->d = c; // (this misuse of s is probably the direct reason for
    the SEGFAULT) Misuse?
    return &s;
    }

    void __k (volatile unsigned int* p){
    t* s;
    char* c = "asdf"; // The colon was a typo.
    s = (t*)p;
    free (s->d);
    s->d = malloc (sizeof (c));
    s->d = c;
    }

    int main (void){
    volatile unsigned int* ptr = __t (); // (what is that equality test
    doing in a declaration?) Fixed.
    __k (ptr); // *ptr, not *p

    t* s;
    s = (t*)ptr; // Ibid.
    printf ("%s", s->d);

    return 0;
    }
    [/CODE]

    Please understand, dwise1_aol, that the actual code I'm compiling was
    not filled with so many typos, but is on an older machine, preventing
    me from doing a copy and paste of the code :D So I retyped it
    manually.


    Nonetheless, it still segfaults.

    In the funciton __t you pointed out that s is an uninitialized pointer.
    How would I initialize a static pointer to a struct correctly?
    [CODE=C]static t* s = malloc (sizeof (*s)); // This obviously wouldn't work with C99[/CODE]

    I get the inkling that I'm referencing the struct incorrectly when defining/initializing (*s).c as well, but I'll get to that when I fix the prior issue.

    Thank you
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,172
    Rep Power
    2222
    static t* s = malloc (sizeof (*s)); // This obviously wouldn't work with C99
    C99 can't handle malloc'ing to a static pointer? I didn't know it was so broken. No wonder nobody I know of would use it.

    Since it's a static pointer, it will retain its value from call to call. However, if you malloc it anew each time, then you will have dropped its previous value with having freed it, thus creating a memory leak that will eat away at your heap until your program suddenly crashes "mysteriously." I would prefer to initialize the pointer to a known invalid value, such as NULL, and then if it's that value I would malloc it once. Eg:
    Code:
        static t* s = NULL;
    
        if (s == NULL)
            s = malloc (sizeof (struct t));
    It's just my personal preference to use the size of the datatype rather than dereferencing the pointer, but I believe that either would work equally well.

IMN logo majestic logo threadwatch logo seochat tools logo