AUTOSAR 规则 A5-0-4 对指针运算的立场

问题描述 投票:0回答:2

AUTOSAR 规则 A5-0-4 规定

指针算术不得与指向非最终的指针一起使用 课程。

它提供了以下理由:

只有当指针的指向类型是正确的时,指针算术才被明确定义 指针等于它所指向的数组的元素类型,否则 该行为是未定义的。只有在以下情况下才能保证此属性: 指针操作数是指向非类类型的指针或指向最终类型的指针 班级类型。

然后给出了一些合规和不合规的例子。其中一项不合规之处让我感到困惑:

void Foo(Base *start, size_t len)
{
  // Non-Compliant: pointer arithmetic on non-final pointer type
  for (Base *iter = start; iter != start + len; ++iter)
  {
    iter->Do();
  }
}

无论任何人不太可能使用普通的 C 数组来存储多态指针,它都存在于 C++ 语言的结构中。

所以我的直觉是上面的代码没有任何问题。

也许我的这个信念是错误的。 或者也许我完全忽略了这个 AUTOSAR 规则试图向读者传达的观点。

有人能比 AUTOSAR 文档更好地解释它吗?

另请参阅 AUTOSAR 规则 A5-0-4,其中给出了示例中使用的完整代码。

c++ polymorphism autosar
2个回答
0
投票

我怀疑你没有抓住要点。考虑这样的事情:

class Base {
   int x;
public:
   virtual void Do() = 0;
   virtual ~Base() = default;
};

class Derived : public Base {
    int y;
public:
    virtual void Do() override {
         ++y;
    }
};

int main() {
    Derived data[10];

    Foo(data, 10); // using definition of `Foo` from question
}

这具有未定义的行为。

Foo
期望接收
Base
数组的开头地址。但我们传递的是指向
Derived
的指针,而不是指向
Base
的指针。由于
Foo
“认为”它正在操作指向基址的指针,因此当其循环执行
++iter
时,它会将地址增加
sizeof(Base)

然而,正如我们所定义的,

Derived
几乎肯定比
Base
大。在增量
iter
几乎可以肯定 won't 指向第二个
Derived
对象时,当我们尝试在该指针上调用
Do
时,事情会向侧面发展(不能保证,但在典型的实现中,它最终会尝试使用
data[0].y
作为 vtable 指针来查找
Do
的地址。


0
投票

如果是的话,所质疑的例子就很好了

void Foo(Base **start, size_t len);

即 start 类型为

Base **
,但每个增量都是
sizeof(Base)
对象而不是
sizeof(Base*)

© www.soinside.com 2019 - 2024. All rights reserved.