0

What is the state of p1, p2 after compiling and running below C snippet code?

char *p1 = malloc(5);
char *p2 = p1 - 3;
*p2 = '\0';
Saeed Hassanvand
  • 931
  • 1
  • 14
  • 31

2 Answers2

5

If you were turning this C code directly into simple machine code on a simple machine, then char *p2 = p1 - 3; would set p2 to point to three bytes earlier in memory than p1, and *p2 = '\0' would write a zero to an improper location. We do not know what is at that location, so we cannot say what the effect is.

However, modern compilers generally do not turn C code directly into simple machine code. They interpret the C code and perform complicated optimizations on it. Because of this, understanding what happens requires using the C standard or documentation for the compiler being used.

What does the C standard tell us about this code? For p1 - 3, the rules about addition with a pointer in C 2018 6.5.6 8 apply:

When an expression that has integer type is added to or subtracted from a pointer,… If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

Because p1 points to an element of object (which may be used as an array) provided by malloc, and p1 - 3 does not point to an element of that array, the behavior is not defined by the C standard. Therefore, if we are using the C standard as a basis for understanding, once p1 - 3 is evaluated, we cannot say what the behavior of the program or the state of p1 and p2 is.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
-1

p1 points to the begin of the allocated memory block. p2 contains the address of the byte three bytes before this block. So the third line will modify a byte outside of the memory block, which will either overwrite some data allocated by other code or corrupt the memory management structures.

  • The behavior of `*p2 = '\0'` is not defined by the C standard. Therefore, using the C standard as a basis for reasoning, it is not possible say that it overwrites some data or corrupts memory. The behavior is **unknown**. In particular, modern optimization software in compilers may make complex transformations to code, with the result that undefined behavior can have unexpected effects. It is not possible to say, based on the C standard, what the state of `p1` or `p2` or memory is after this code executes. – Eric Postpischil Dec 02 '18 at 12:24
  • 2
    Furthermore, `char *p2 = p1 - 3` also has undefined behavior. The C standard does not define the result of performing address arithmetic that would produce a result outside of the addressed object (the memory provided by `malloc` in this case). (For purposes of address arithmetic, the address one element beyond the end of the array is considered as part of the array.) So we cannot say `p2` points to an address three bytes before the block. – Eric Postpischil Dec 02 '18 at 12:26