Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Question about an example from rule 9-3-1
#1
Hi MISRA,

I have a question about the following example from rule 9-3-1:
Code:
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!
<t></t>
Reply
#2
Maybe this extended and commented sample answers your question:

Code:
#include

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;
}
<t></t>
Reply
#3
dg1980 Wrote:Maybe this extended and commented sample answers your question:

Code:
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:
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.
<t></t>
Reply
#4
dg1980 Wrote:Maybe this extended and commented sample answers your question:

Code:
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:
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.
<t></t>
Reply
#5
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:
#include

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;
}
<t></t>
Reply
#6
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.

Quote: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.
<t></t>
Reply
#7
The code doesn't violate the rule, as the value returned by the function does not allow any class member to be modified
Posted by and on behalf of
the MISRA C++ Working Group
Reply


Forum Jump:


Users browsing this thread: 5 Guest(s)