MISRA Discussion Forums

Full Version: Rule 7-5-3 and storing a reference for later use
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello,

I am curious if Rule 7-5-3 is only applicable when a reference to a parameter that is passed by const reference is returned from a function, but also if that reference is stored and then used later.

The rationale of the rule states that "It is implementation-defined behaviour whether the reference parameter is a temporary object or a reference to the parameter." and then goes on to say that a temporary object will be destroyed when the function returns and that using an object after its destruction will lead to undefined behaviour.

Considering the following code:
Code:
class TestConstRef
{
public:
  TestConstRef(const T& aT) : mT(aT) {}
  ~TestConstRef() {}

private:
  const T& mT;
};

If I understand the rule correctly, the parameter aT could be a temporary object which will be destroyed when the constructor exits and when the member reference mT is used later, the temporary object that it refers to may (depending on the implementation) no longer exist and that will lead to undefined behaviour.

Could I ask:
  • Is this understanding correct?
  • Is so, why is only returning the reference explicitly covered by the rules, and not storing the reference as in the code snippet above?
Interesting point.

I think the rule refers to chapter 5.2.2 paragraph 5 of ISO/IEC 14882:2003:

Quote:Where a parameter is of const reference type a temporary object is introduced if
needed (7.1.5, 2.13, 2.13.4, 8.3.4, 12.2). In addition, it is possible to modify the values of nonconstant
objects through pointer parameters.

However, you can make the same mistake by storing a reference to a temporary object:

Code:
class cFoo
{
public:
  cFoo(const int& arg) : ref(arg){}
  const int& get(void) const{return ref;}
private:
  const int& ref;
};

const cFoo& init(void){return *(new cFoo(2));}

int main(void)
{
  const cFoo& f = init();// creates temporary int 2
  int x = 5;// overwrites temporary int
  return f.get() + x;// program returns 5 (not 7) - ignore the memory leak:)
}
I am also concerned about the following type of snippet:
Code:
#include

class TestConstRef
{
public:
  TestConstRef(const int32_t& aInt) : mInt(aInt) {}
  ~TestConstRef() {}

private:
  const int32_t& mInt;
};

int main(void)
{
  const double aDouble = 45.3;
  const TestConstRef constRef(aDouble); // Temporary int32_t is created here
}

The line where the temporary int32_t is created is perfectly legal code, but the reference to it will be lost when the constructor exits.
However, the compiler will not warn you whether a temporary is created or not.

So, unless you have some other way to ensure absolutely that a temporary is not created for this sort of example, you could end up with a reference to a temporary.

Furthermore, the MISRA rule seems to suggest that temporaries can be introduced on an implementation-defined basis.

This seems to be borne out by the chapter 5.2.2 paragraph 5 of ISO/IEC 14882:2003 mentioned - which states that a temporary object is introduced "if needed". It does not specify what "if needed" means - so could this not vary system-by-system, such that even if you inspect the code and decide for yourself that temporaries are not needed, the compiler might decide otherwise?
Sorry, this was a double-post of the previous post - as the system gave me an error message - but I can't seem to find a way to delete it.
We agree with your interpretation of 7-5-3, and we recognise the limted scope of the current rule

We are currently working on a new version of the standard, and the aim for this rule is that we move toward the requirements of MISRA C:2012 18.6 'The address of an object ... shall not be copied to another object that persists after the first object has ceased to exist'