Regarding the error, rule 2.2 is about not having any "dead code" in your program.
In the function, mem_ptr = NULL;
sets the local variable mem_ptr
to null, not the one passed. So that code line does nothing. This is the reason for the error and it's a common beginner FAQ, see Dynamic memory access only works inside function for details.
In the function-like macro, the passed pointer would however get changed by (p) = 0;
. But if you aren't using the pointer after setting it to null, it's still regarded as "dead code" since the assignment is then strictly speaking pointless (although good practice). We can't tell since you didn't post the calling code nor the actual pointer declaration.
But there's some far more serious big picture issues here:
Using MISRA-C and dynamic memory allocation at the same time is nonsensical. They are pretty much mutually exclusive. Embedded systems in general don't use dynamic allocation, especially not bare metal/RTOS MCU applications where it simply doesn't make any sense.
Dynamic allocation is particularly banned in mission-critical/safety-related software. This is not only banned by MISRA, but by any coding standard out there. It is also banned by generic safety standards like IEC 61508, ISO 26262, DO 178 etc.
Safety and MISRA aside, your macro is still nonsense since free()
on a null pointer is a well-defined no-op. See the definition of free
in C17 7.22.3.3:
void free(void *ptr);
/--/ If ptr is a null pointer, no action occurs.
So all the macro achieves is to obfuscate the code and slow it down with an extra, pointless branch.
The correct solution here is to nuke this macro, then take a step back and consider what you are even doing with this project. Start with the requirements. Why do you need MISRA-C, does somebody in this project know what they are doing, if not - who should we hire to help with this project. And so on. You need at least one C veteran on the team for a project with MISRA-C or otherwise the project is doomed.