0

Following are two code snippets. One worked correctly but the other failed.

Main Function

int main
{
  int *x,*y,n,*c;
  //some code
  c=myfunc(x,y,n);
  //rest code
}

Here is the code that worked:

int * myfunc(int *a, int *b, int n)
{
  int *s,i,*t;
  for(i=0;i<n;i++)
      s[i]=x[i]+y[i];
  t=s;
  return s;
}

And here is the code that doesn't work

int * myfunc(int *a, int *b, int n)
{
  int s[100],i,*t;
  for(i=0;i<n;i++)
      s[i]=x[i]+y[i];
  t=&s[0];
  return t;
}

What happens here is that even though the returned value is the correct address(tested and checked) the contents seemed to get modified on its own. However this did not seem to be the case in the first scenario.

Not only that but the entire array of s[100] has different contents at the end of the executed query. Which basically means the contents of all these addresses are getting modified because of some random reason.

The compiler used was Turbo C.


EDIT

Question in Straight forward terms:

Why does the contents of s when initialized as s[100] get reset after returning and where as contents of s when initialized as *s does not reset. Please note: I Have Not used malloc() or functions that has anything to do with stacks anywhere on my code.

jww
  • 97,681
  • 90
  • 411
  • 885
n0tty
  • 3
  • 3
  • That question doesn't quite get to the point of my query. My doubt is, why does *s initialization work and not s[100]. Rest of my code is just plain and same. No malloc() function used, no complication done. – n0tty Oct 28 '14 at 19:42
  • See my other comment. In both cases, as far as we can see (apart from the hidden, top-secret initialization of `int *s`), you've got undefined behavior. There's no reason to expect either version to do anything in particular. Move some code around, re-order some function calls, the other version may now *appear* to work. Neither *should* work, for any good reason. – Paul Roub Oct 28 '14 at 19:45
  • Sorry for the top secret initialization lol... I thought it would just be a piece of junk code because nothing special is done in it. Added the entire function in the question. Thanks – n0tty Oct 28 '14 at 19:55

2 Answers2

0

In the code that doesn't work, s[100] is an array on the stack, and goes out of scope when the function returns. In the working code, you don't show how s is allocated, but presumably it's with a malloc, or some other non-stack allocation.

In general, you should not return pointers to stack variables because the stack variables will get overwritten as soon as the function returns.

PS. get a real compiler already :)

user3386109
  • 34,287
  • 7
  • 49
  • 68
  • In the working code, I initialized _s_ as _*s_, which is just another pointer. And the operations done on it were ditto same as what was done on the s[100]. I get the point that the array declaration is in local scope of the function, but then do pointers have a global scope? – n0tty Oct 28 '14 at 19:21
0

Nothing random about it. You're returning the address of a local variable, which ceases to exist once the function returns. That space is freed up for future function calls, variables, etc.

int * myfunc(int *a, int *b, int n)
{
   int s[100],i,*t;
   //some operation
   t=&s[0];
   return t;
}              // <!-- s is no longer valid after this point, so t is pointing nowhere
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
  • In the working code, I initialized _s_ as _*s_, which is just another pointer. And the operations done on it were ditto same as what was done on the s[100]. I get the point that the array declaration is in local scope of the function, but then do pointers have a global scope? – n0tty Oct 28 '14 at 19:22
  • No. But then, you never showed us how `s` was initialized in the working code. I assumed you'd allocated memory (via `malloc()`, etc.) -- in which case scope has nothing to do with it. `malloc()`-ed memory exists until you call `free()` on it. – Paul Roub Oct 28 '14 at 19:24
  • Hey! That is fine! malloc() and other functions were not used in the code. But the question is, **why does initializing int *s and then doing t=s; and returning t work fine? Isn't that a local variable too? Or does defining a pointer make it globally usable?** – n0tty Oct 28 '14 at 19:38
  • No. Again, you never showed how `int *s` was initialized. If it's *uninitialized*, and you're lucky enough to be able to use it's contents, *that's* random chance. Using an uninitialized pointer, like accessing a local variable's space after the function has exited, is undefined behavior. In some cases it may appear to work, in others the breakage is more obvious. If `int *s` is pointing at a local array, the difference in the layout of the code, or the calling order, or the phase of the moon, or *anything* may be responsible for the accidental "good" behavior. – Paul Roub Oct 28 '14 at 19:41
  • `int * myfunc(int *x, int *y, int n) { int *s,i,*t; for(i=0;i – n0tty Oct 28 '14 at 19:43
  • Yeah, there's no reason to expect that to work, either. Every `s[i] = ...` could just as well crash your program, since `s` is pointing into unknown territory. It happens that, at the moment, that unknown territory is someplace not-immediately-dangerous. – Paul Roub Oct 28 '14 at 19:47
  • @PeterSmith So basically the code that worked was total luck? I however still do not see why it did not get re-initialized like the other code that failed to work you know. However, you are right, when I code hard applications, I'll take care of the unknown territory and denial of service bugs that might crop up out of it! – n0tty Oct 28 '14 at 19:52