Page 1 of 1

Question about an example from rule 9-3-1

Posted: Fri Apr 07, 2017 6:50 am
by cxlin
Hi MISRA,

I have a question about the following example from rule 9-3-1:

Code: Select all

class C {
public:
  C ( int &b_ ) : b( b_ ) { }

  int *getB () const
  {
    return &b;  // Non-compliant
  }
private:
  int &b;
}
Here `getB` actually returns a pointer to the object that `b` referenced, not the member `b` itself. And that object doesn't seem to satisfy the definition of "class data" by 1) it's not non-staitc member data, and 2) it's not a resource acquired in the constructor or released in the destructor. So I'm not sure why this is a Non-compliant case. Could you help to clarify a bit? Thanks!

Re: Question about an example from rule 9-3-1

Posted: Fri Apr 07, 2017 8:23 am
by dg1980
Maybe this extended and commented sample answers your question:

Code: Select all

#include <stdint.h>

namespace nMISRA
{
  class C {
  public:
    C ( int32_t &b_ ) : b( b_ ) { }

    int32_t *getB () const
    {
      return &b;  // Non-compliant
    }
    int32_t getState(void) const{return b;}
  private:
    int32_t &b;
  };
}

int32_t main(void)
{
  int32_t ret = 0;
  int32_t state = 0;
  nMISRA::C c(state);
  *c.getB() = 1;// const member changing the state of the object, triggering error condition below
  if (c.getState() != 0)
  {
    ret = -1;// error
  }
  return ret;
}

Re: Question about an example from rule 9-3-1

Posted: Fri Apr 07, 2017 9:45 am
by cxlin
dg1980 wrote:Maybe this extended and commented sample answers your question:

Code: Select all

int32_t main(void)
{
  int32_t ret = 0;
  int32_t state = 0;
  nMISRA::C c(state);
  *c.getB() = 1;// const member changing the state of the object, triggering error condition below
  if (c.getState() != 0)
  {
    ret = -1;// error
  }
  return ret;
}
Well, `state` is not part of the object `c` (and likely not "class data"). It doesn't make much sense if this rule is to enforce that `getB` only return a const handler of `state`, because `state` is already in scope and could be modified without calling `getB`!

Code: Select all

  int32_t state = 0;
  nMISRA::C c(state);
  state = 1;
  if (c.getState() != 0)
  ...
So I don't think the original example follows the rationale of the rule and thus the original question.

Re: Question about an example from rule 9-3-1

Posted: Fri Apr 07, 2017 9:45 am
by cxlin
dg1980 wrote:Maybe this extended and commented sample answers your question:

Code: Select all

int32_t main(void)
{
  int32_t ret = 0;
  int32_t state = 0;
  nMISRA::C c(state);
  *c.getB() = 1;// const member changing the state of the object, triggering error condition below
  if (c.getState() != 0)
  {
    ret = -1;// error
  }
  return ret;
}
Well, `state` is not part of the object `c` (and likely not "class data"). It doesn't make much sense if this rule is to enforce that `getB` only return a const handler of `state`, because `state` is already in scope and could be modified without calling `getB`!

Code: Select all

  int32_t state = 0;
  nMISRA::C c(state);
  state = 1;
  if (c.getState() != 0)
  ...
So I don't think the original example follows the rationale of the rule and thus the original question.

Re: Question about an example from rule 9-3-1

Posted: Fri Apr 07, 2017 10:11 am
by dg1980
As soon as you store a reference, it becomes class data.
I slightly reworked the example, to make it even more obvious what evil code you could write, if this was not treated a violation of 9-3-1:

Code: Select all

#include <stdint.h>

namespace nMISRA
{
  class C {
  public:
    C ( int32_t &b_ ) : b( b_ ) { }

    int32_t *getB () const
    {
      return &b;  // Non-compliant
    }
    int32_t getState(void) const{return b;}
  private:
    int32_t &b;
  };

  void foo(const C& rhs, int32_t s)
  {
    *rhs.getB() = 1;// !!!wow, a const ref and a const member change the state of the object without even knowing the variable defined in main!!!
  }
}

int32_t main(void)
{
  int32_t ret = 0;
  int32_t state = 0;
  nMISRA::C c(state);
  
  nMISRA::foo(c, 1);
  if (c.getState() != 0)
    ret = -1;// error
  return ret;
}

Re: Question about an example from rule 9-3-1

Posted: Fri Apr 07, 2017 11:59 am
by cxlin
dg1980 wrote:As soon as you store a reference, it becomes class data.
To me that's not clear from the definition of "class data" (as mentioned in the original post). And this is exactly the question I'm asking MISRA to confirm.

The same goes with a resource that's not allocated by the constructor or released by the destructor, but pointed to by a pointer member.

Note the definition of "class data" actually made clear that static members are not "class data", and in the example the resource reference by `b` could be shared by multiple objects and acts basically the same as a static member.
I slightly reworked the example, to make it even more obvious what evil code you could write, if this was not treated a violation of 9-3-1:
The evilness of your code does not come from not following 9-3-1, but from the fact that a member referencing a shared object (with automatic storage). Removing `const` from `getB` and some other functions will make the code 9-3-1 compliant (under your interpretation) but doesn't really make it less evil.

Re: Question about an example from rule 9-3-1

Posted: Mon Jul 10, 2017 11:49 am
by misra cpp
The code doesn't violate the rule, as the value returned by the function does not allow any class member to be modified