In the following example:
void 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);
}
MISRA 5-2-8 and 5-2-7 violations are reported.
How I can remove this violation ?
I need someone experienced with C++ static analysis to help me. I am hitting my head with this stupid rules from few days.
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.
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.
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;
}
How is supposed to do it according to MISRA?
So are there any solutions at all?
EDIT: 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 - document the MISRA deviations one by one and explain why casts are Ok, explain how this has been tested (Q.Q. suggestion)
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.
char_t
? Do you have to use it? – Pacesettervoid*
? – Lashandralasharchar
type for anything but C strings, namely the implementation-defined signedness. If you are only usingchar
for strings, you are fine. If you are using it for arithmetic, other than what's listed as valid exceptions by MISRA, creating achar_t
typedef is not the correct way to go: you should then have useduint8_t
orint8_t
. – Locklinvoid *
to other type assumes the pointer to be properly aligned, otherwise UB. – Lidiachar*
tovoid*
in the code does not use a cast. A cast is something you write in your source code to tell the compiler to do a conversion. – Hedronenum
may remove Misra warning, but not sure it is better. – Finfootuint8_t
differently thanunsigned char
when it comes to aliasing would be so utterly useless that everyone using it deserve all the bugs they can get. It doesn't matter what the standard says: just because an implementation conforms to the standard, it doesn't mean that the implementation should actively seek to be useless in real-world applications. If I encountered a compiler which gave alias-related bugs because I useuint8_t
instead ofchar
, I'd throw it out the window, the standard be damned. – Locklin