c - Function returns unexpected pointer -
i'm working on simple c program nested structures , unions, , got problem returning pointer char array.
here code :
#define bufsize 32 typedef enum { s1 = 0, s2 } type_t; typedef struct { int x, y; char value[bufsize]; } s1_t; typedef struct { s1_t s; char value2[bufsize]; } s2_t; typedef struct { type_t t; union { s1_t s1; s2_t s2; }; } s3_t; s3_t* new_s1(int x, int y, char* value) { s3_t* s; if ((s = malloc(sizeof(s3_t))) == null) return null; memset(s, 0, sizeof(s3_t)); s->t = s1; s->s1.x = x; s->s1.y = y; strncpy(s->s1.value, value, bufsize); return s; } s3_t* new_s2(int x, int y, char* value, char* value2) { s3_t* s; if ((s = malloc(sizeof(s3_t))) == null) return null; memset(s, 0, sizeof(s3_t)); s->t = s2; s->s2.s.x = x; s->s2.s.y = y; strncpy(s->s2.s.value, value, bufsize); strncpy(s->s2.value2, value2, bufsize); return s; } // problem comes function ? char* get_value(s3_t s) { return (s.t == s1) ? s.s1.value : s.s2.s.value; } int main(void) { s3_t *a, *b; char *p1, *p2; if ((a = new_s1(1, 2, "a")) == null) return 1; if ((b = new_s2(1, 2, "abcd", "val2")) == null) return 2; p1 = get_value(*a); printf("a (%p) => p1 : (%p - %s) - (%p - %s)\n", a, p1, p1, a->s1.value, a->s1.value); p2 = get_value(*b); printf("b (%p) => p1 : (%p - %s) - (%p - %s)\n", b, p2, p2, b->s2.s.value, b->s2.s.value); printf("strcmp(p1,p2) = %d\n", strcmp(p1, p2)); free(a); free(b); return 0; }
and output :
a (0x1974010) => p1 : (0x7fff085df16c - a) - (0x197401c - a) b (0x1974070) => p2 : (0x7fff085df16c - abcd) - (0x197407c - abcd) strcmp(p1,p2) = 0
the problem pointers returned get_value
function same, if params not ("a", "b"), strcmp()
returns 0. see, get_value(*a)
returns pointer 0x7fff085df16c
, why not 0x197401c
?
because pointers returned same, if change main in :
// ... p1 = get_value(*a); p2 = get_value(*b); printf("a (%p) => p1 : (%p - %s) - (%p - %s)\n", a, p1, p1, a->s1.value, a->s1.value); printf("b (%p) => p2 : (%p - %s) - (%p - %s)\n", b, p2, p2, b->s2.s.value, b->s2.s.value); printf("strcmp(p1,p2) = %d\n", strcmp(p1, p2)); // ...
the string value of p1 overwritten string value of p2. output looks :
a (0x1156010) => p1 : (0x7fffb81d8cbc - abcd) - (0x115601c - a) b (0x1156070) => p2 : (0x7fffb81d8cbc - abcd) - (0x115607c - abcd) strcmp(p1,p2) = 0
of course, can fix changing function get_value
make copy string , return pointer.
char* get_value(s3_t s) { char* p; if ((p = malloc(bufsize)) == null) return null; strncpy(p, ((s.t == s1) ? s.s1.value : s.s2.s.value), bufsize); return p; }
but don't (and want to) understand why pointer returned get_value
different pointer in structure. did miss ?
structure/union types (all types, really) in c passed by-value.
so in code:
char* get_value(s3_t s) { }
the compiler allocate s3_t
on stack , caller copy contents stack space allocated.
by returning contents of s.s1.value
, you're returning pointer space allocated on stack. memory gets deallocated when get_value()
returns caller.
some compilers kind enough warn when make error. example, took get_value()
clang
-wall
, got following:
$ /opt/llvm+clang-3.4/bin/clang -wall -o pbv.o -c pbv.c pbv.c:28:24: warning: address of stack memory associated local variable 's' returned [-wreturn-stack-address] return (s.t == s1) ? s.s1.value : s.s2.s.value; ^ 1 warning generated.
Comments
Post a Comment