MISRA C ++ 2008违反规则5-2-7:具有指针类型的对象不得直接或间接转换为不相关的指针类型 [英] MISRA C++ 2008 Rule 5-2-7 violation: An object with pointer type shall not be converted to an unrelated pointer type, either directly or indirectly

查看:220
本文介绍了MISRA C ++ 2008违反规则5-2-7:具有指针类型的对象不得直接或间接转换为不相关的指针类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下示例中:

bool bad_function()
{  
  char_t * ptr = 0;

  // MISRA doesn't complains here, it allows cast of char* to void* pointer
  void* p2 = ptr;

  // the following 2 MISRA violations are reported in each of the casts bellow (two per code line)
  // (1) Event misra_violation:     [Required] MISRA C++-2008 Rule 5-2-7 violation: An object with pointer type shall not be converted to an unrelated pointer type, either directly or indirectly
  // (1) Event misra_violation:     [Required] MISRA C++-2008 Rule 5-2-8 violation: An object with integer type or pointer to void type shall not be converted to an object with pointer type
  ptr = (char_t*) (p2); 
  ptr = static_cast<char_t*> (p2); 
  ptr = reinterpret_cast<char_t*> (p2); 

  return true;
}

报告了违反MISRA 5-2-8和5-2-7的情况.

MISRA 5-2-8 and 5-2-7 violations are reported.

我如何删除此违规行为?

How I can remove this violation ?

我需要具有C ++静态分析经验的人员来帮助我.从几天以来,我一直在用这种愚蠢的规则打我的头.

I need someone experienced with C++ static analysis to help me. I am hitting my head with this stupid rules from few days.

根据MISRA C ++标准(MISRA-Cpp-2008.pdf:规则5-2-7(必需):具有指针类型的对象不得直接或间接转换为不相关的指针类型.

According to MISRA C++ standard (MISRA-Cpp-2008.pdf: Rule 5-2-7 (required): An object with pointer type shall not be converted to an unrelated pointer type, either directly or indirectly.

好,但是我们有很多代码,例如需要将地址转换为char*,然后将其与std::ifstream一起使用,而read(char* buffer, int length)函数则需要将地址类型转换为(char_t*).那么,按照MISRA的说法,有人可以使用C ++进行编程,而根本不使用任何强制转换?该标准并未说明必须如何进行指针转换.

Ok but we have a lot of code which for example needs to convert address to char* and then to use it with std::ifstream, which read(char* buffer, int length) function requires to type cast the address to (char_t*). So how according to MISRA guys someone can program in C++ and not using at all any casts? The standard doesn't say HOW pointer conversion then must be done.

在生产代码中,我的问题是使用预读的数据结构中的文件中的 std:ifstream 进行读取的文件读取操作:

In my production code my problems are in file reading operations using read with std:ifstream from files in predefined data structures:

if (file.read((char_t*)&info, (int32_t)sizeof(INFO)).gcount() != (int32_t)sizeof(INFO)
{
                LOG("ERROR: Couldn't read the file info header\n");
                res = GENERAL_FAILURE;
}

根据MISRA应该怎么做?

How is supposed to do it according to MISRA?

那么,有什么解决办法吗?

So is there are any solutions at all?

Peter和Q.Q.答案都是正确的,似乎MISRA确实希望在不进行任何强制转换的情况下完成所有工作,如果项目处于最后阶段,则很难做到.有两种选择:

Peter and Q.Q. answers are both correct, it seems that MISRA really wants to do everything without any casts which is hard to be done if the project is in the final stage. Therea are two options:

1-逐一记录MISRA的偏差,并说明演员表为什么还可以,并说明如何对其进行测试(Q.Q.建议)

1 - document the MISRA deviations one by one and explain why casts are Ok, explain how this has been tested (Q.Q. suggestion)

2-将char类型的字节数组用于file.read(),然后在安全地读取文件内容后,将字节数组转换为标头内容,这必须对每个成员一一完成,因为如果您转换char *到int32_t,这再次违反了规则5-2-7.有时这是太多的工作.

2 - use byte array from char type for file.read(), then after safely reading the file content cast the byte array to the headers content, this must be done for each member one by one because if you cast char* to int32_t this is again Rule 5-2-7 violation. Sometimes it is too much work.

推荐答案

MISRA规则的基本原因是,将任何指针/地址转换为任何非空指针都可以使用该地址,就好像它是一个与之不同的对象一样其实是.在这种情况下,编译器会抱怨隐式转换.使用类型转换(或C ++ _cast运算符)实质上可以停止编译抱怨,并且-在太多情况下-取消引用指针会带来不确定的行为.

The basic reason for the MISRA rule is that converting any pointer/address to any non-void pointer allows using that address as if it is a different object than it actually is. The compiler would complain about an implicit conversion in those cases. Using a typecast (or C++ _cast operators) essentially stops the compile complaining and - in too many circumstances to count - dereferencing that pointer gives undefined behaviour.

换句话说,通过强制类型转换,您将引入潜在的不确定行为,并关闭编译器向您发出警告的所有可能性. MISRA认为这是一个坏主意....尽管许多程序员出于易于编码的考虑而认为它在某些情况下是个好主意.

In other words, by forcing a type conversion, you are introducing potential undefined behaviour, and turning off all possibility of the compiler alerting you to the possibility. MISRA think that is a bad idea .... not withstanding the fact that a lot of programmers who think in terms of ease of coding think it is a good idea in some cases.

您必须认识到,MISRA检查的原理不像典型的程序员那样关心编程的简便性,而是更关注防止未定义(或实现定义或未指定等)行为通过所有检查并导致以下情况的情况:可能造成伤害的野外"代码.

You have to realise that the philosophy of MISRA checks is less concerned about ease of programming than typical programmers, and more concerned about preventing circumstances where undefined (or implementation defined or unspecified, etc) behaviours get past all checks, and result in code "in the wild" that can cause harm.

问题是,在您的实际用例中,您依赖于file.read()正确填充名为(c6)的(大概)数据结构.

The thing is, in your actual use case, you are relying on file.read() correctly populating the (presumably) data structure named info.

if (file.read((char_t*)&info, (int32_t)sizeof(INFO)).gcount() != (int32_t)sizeof(INFO)
{
            LOG("ERROR: Couldn't read the file info header\n");
            res = GENERAL_FAILURE;
}

您需要做的工作是更加努力,以提供将通过MISRA检查器的有效代码.像

What you need to do is work a bit harder to provide valid code that will pass the MISRA checker. Something like

std::streamsize size_to_read = whatever();
std::vector<char> buffer(size_to_read);  

if (file.read(&buffer[0], size_to_read) == size_to_read)
{
      //  use some rules to interpret contents of buffer (i.e. a protocol) and populate info
      // generally these rules will check that the data is in a valid form
      //   but not rely on doing any pointer type conversions
}
else
{
            LOG("ERROR: Couldn't read the file info header\n");
            res = GENERAL_FAILURE;
}

是的,我意识到这比简单地使用类型转换以及允许二进制保存和读取结构要复杂得多.但是,这是休息时间.如果您做对了,除了可以克服MISRA检查器之外,这种方法还有其他优点,例如文件格式完全独立于用于编译代码的编译器.您的代码取决于实现定义的数量(结构中成员的布局,sizeof的结果),因此,如果代码是使用编译器A生成的,则可能无法读取由编译器B生成的代码生成的文件. MISRA要求的常见主题之一是减少或消除任何行为可能对实现定义的数量敏感的代码.

Yes, I realise it is more work than simply using a type conversion, and allowing binary saves and reads of structs. But them's the breaks. Apart from getting past the MISRA checker, this approach has other advantages if you do it right, such as the file format being completely independent of what compiler is used to build your code. Your code depends on implementation-defined quantities (the layout of members in a struct, the results of sizeof) so your code - if built with compiler A - may be unable to read a file generated by code built with compiler B. And one of the common themes of MISRA requirements is reducing or eliminated any code with behaviour that may be sensitive to implementation-defined quantities.

注意:您还将char_t *传递给std::istream::read()作为第一个参数,而将int32_t传递给第二个参数.两者实际上都是不正确的.实际参数的类型为char *std::streamsize(可能是,但不一定是int32_t).

Note: you are also passing char_t * to std::istream::read() as first argument and an int32_t as the second argument. Both are actually incorrect. The actual arguments are of type char * and std::streamsize (which may be, but is not required to be an int32_t).

这篇关于MISRA C ++ 2008违反规则5-2-7:具有指针类型的对象不得直接或间接转换为不相关的指针类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆