18

For example:

void func1(){
    int i = 123;
    func2(&i);
}
void func2(int *a){
    *a = 456;
}

When func1 calling func2, a pointer to local variable is passed to func2 -- the pointer is pointed to the stack. Is this safe for the rules of C?

Thanks.

alk
  • 66,653
  • 10
  • 83
  • 219
Albert Zhang
  • 687
  • 1
  • 7
  • 19
  • 3
    Using a pointer to a variable after the variable is destroyed is unsafe. You aren't doing that here. – user253751 Feb 17 '15 at 08:09
  • Possible duplicate of [Safe to pass pointer to auto variable to function?](http://stackoverflow.com/questions/17798785/safe-to-pass-pointer-to-auto-variable-to-function) – ravron Feb 10 '16 at 20:22

6 Answers6

20

The scope of i is func1 and it outlives the call to func2. So it is perfectly safe.

juanchopanza
  • 210,243
  • 27
  • 363
  • 452
5

As stated in most of the answers before, it is perfectly safe to pass the pointer to func2() in your special case.

In a real world piece of software however, I consider this harmful as you don't have control on what func2() is doing with your variable. func2() may create an alias to its parameter to use it asynchronously at a later point in time. And at that time, the local variable int i may be gone when this alias is used later.

So from my point of view passing a pointer to a local (automatic) variable is extremely dangerous and should be avoided.

You may do so if you declare the variable in func1() as static int i;

In that case, it is ensured, that the memory for i won't get recycled and overwritten. However you will need to setup some Mutex locking for access control to this memory in a concurrent environment.

To illustrate this problem here is some code I just stumbled in yesterday while doing software testing at my customer. And yes, it crashes...

void func1()
{
  // Data structure for NVMemory calls
  valueObj_t NVMemObj;

  // a data buffer for eeprom write
  UINT8 DataBuff[25];
  // [..]
  /* Assign the data pointer to NV Memory object */
  NVMemObj.record = &DataBuff[0];
  // [..]
  // Write parameter to EEPROM.
  (void)SetObject_ASync(para1, para2, para3, &NVMemObj);
  return;
}

void SetObject_ASync(para1, para2, para3, valueObj_t *MemoryRef)
{
  //[..]
  ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr  = MemoryRef->record;
  //[..]
  return;
}

In this case, the data in the DataBuff is long gone when the pointer in ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr is used to store the data to the EEPROM.

To fix this code, it is at least necessary to declare static UINT8 DataBuff[25]; Additionally, it shall be considered to also declare static valueObj_t NVMemObjas we don't know what the called function is doing with that pointer.

To put it briefly: TL;DR

Even though it is legal in the C-language I consider it as harmful to pass pointers to automatic variables in a function call. You never know (and often you don't want to know) what exactly the called function does with the passed values. When the called function establishes an alias, you get in big trouble.

Just my 2 cents.

opt12
  • 300
  • 3
  • 10
  • 4
    "func2() may create an alias to its parameter to use it asynchronously at a later point in time". Yet the same could be said about malloced memory you pass into a function...it might create an alias to it which it tries to access after the caller later frees the memory. The point here is not the caller doing anything wrong, but the *called function* keeping references (where? in a global?) to it's own args that it re-uses in *later calls*. Also consider that it's a safer starting point as they don't need to be freed. TLDR; automatic variables=good. Functions keeping pointers to their args=bad. – aaa90210 Apr 05 '17 at 23:12
  • @aaa90210 But the example is not using an malloc'ed memory. It is using a `static` buffer, which is guaranteed to exist during the entire lifetime of the process. So I agree, malloc or C++ `new` are dangerous. But static with mutexes isn't. – deLock Jan 15 '20 at 16:47
2

Yes it is safe to pass a pointer to a local variable but you can't return a pointer to an automatic local variable from a function.

haccks
  • 97,141
  • 23
  • 153
  • 244
2

Yes, your code is safe.

As long as the object's lifetime is not over, it's safe to pass local variables like you do.

P.P
  • 106,931
  • 18
  • 154
  • 210
1

Is this safe for the rules of C?

What you are doing is safe as the local variable is still valid and within the scope. Accessing the local varaible outside of its scope is undefined behvaior but this is totally fine

Gopi
  • 19,499
  • 4
  • 21
  • 35
1

In your case, you can safely use &i till the time i is valid.

Now, as we can see i has a lifetime till the end of func1(). As, the func2() is being called from the func1() and the func1() has not yet finished execution, so, i is still valid.

That's why , usually passing the address of a local variable to another function is usually allowed (the variable's lifetime is not over) but, returning the address of a local variable (immediately after return, local variables of the function cease to exist) is not allowed.

TL;DR :You can safely use &i as the argument of func2() as shown here.

Sourav Ghosh
  • 127,934
  • 16
  • 167
  • 234
  • *scope* applies to identifiers (not variables) and it means where that identifier is visible, so `i` is not in scope in `func2`. Perhaps you're looking for *lifetime*. – M.M Feb 17 '15 at 09:29