Is undefined behavior the address of an uninitialized pointer?

N1570 claims this behavior is undefined:

Β§J.2 / 1 The value of an object with automatic storage duration is used while it is undefined (6.2.4, 6.7.9, 6.8).

And in this case, our pointer has an undefined value:

Β§6.7.9 / 10 If an object with automatic storage duration is not initialized explicitly, its value is undefined. If an object that has a static or storage duration of threads is not initialized explicitly, then:

- if it has a pointer type, it is initialized with a null pointer;

Then I assume that the following test program demonstrates undefined behavior:

#include <stdio.h> int main(void) { char * ptr; printf("%p", (void*)&ptr); } 

My motivating concern is the strtol function. First, let me quote the parts of the N1570 related to the endptr parameter:

Β§7.22.1.4 / 5 If the sequence of objects has the expected shape and the value of the base is zero, the sequence of characters starting with the first digit is interpreted as an integer constant in accordance with rule 6.4.4.1. [...] The pointer to the final string is stored in the object pointed to by endptr , provided that endptr not a null pointer.

Β§7.22.1.4 / 7 If the sequence of items is empty or does not have the expected shape, the conversion is not performed; the nptr value is equally stored in the object pointed to by endptr , provided that endptr not a null pointer.

This means that endptr must point to an object, and that endptr at some point. For example, this implementation does this :

 if (endptr != 0) *endptr = (char *)(any ? s - 1 : nptr); 

However, this highly endptr answer , as well as this manual page and show endptr passed to endptr is uninitialized. Is there an exception that makes this non-undefined behavior?

+5
source share
5 answers

In this expression:

&ptr

operand address & , i. The address of the ptr object, but the ptr object is never evaluated.

(C11, 6.3.2.1p2) "Except when it is the operand of the sizeof operator, the unary operator and the operator, ++ operator, the operator is either the left operand of the operator. Or the assignment operator, a value l that does not have an array type is converted to a value stored in the specified object (and is no longer an lvalue), this is called an lvalue conversion. "

+3
source

The value of the pointer and its address do not match.

 void *foo; 

This pointer is undefined, but the address is foo , i.e. the value of &foo must be well defined (because otherwise we cannot access it).

At least that my intuitive understanding, I have not dug up the standard now, I just think that you are reading it incorrectly.

When you talk about code, they are sometimes confused ("what is the address of this pointer?" May mean "what is the meaning of this pointer, what address does it indicate?"), But they are really different.

+9
source

Not. This is not undefined behavior. Only ptr uninitialized and has an undefined value, but &ptr has the correct value.

What does the standard quote on strtol mean:

... If the sequence of objects is empty or does not have the expected shape, the conversion is not performed; the nptr value is stored in the object pointed to by endptr, provided that endptr is not a null pointer.

This above quote speaks of a call like this:

 strtol(str, 0, 10); 

The call on the manual page and the related answer are fine.

+2
source

See this example.

 char * ptr; 

Since ptr does not point to any object, dereferencing it causes undefined behavior. But when you pass your strtol address with syntax

 long int strtol(const char *nptr, char **endptr, int base); 

in a statement

 long parsed = strtol("11110111", &ptr, 2); 

The endptr parameter points to the ptr object, and by default it will not call any UBs.

+2
source

I only have access to N1256, but I will be surprised if any significant change occurs.

The most appropriate section is "6.5.3.2 Address and Indirection Operators"

And, in particular, paragraph 3 (my emphasis):

Semantics

3 Unary and the operator gives the address of its operand. If the operand is of type '' type '', the result is of type '' pointer to type ''. If the operand is the result of a unary * operator, and neither the operator is evaluated, and the result looks as if both were omitted, except that the restrictions on the operators are still applied and the result is not an lvalue value. Similarly, if the operand is the result of the [] operator, neither the operator nor the unary *, which is implied by [], and the result looks as if the operator had been deleted and the [] operator was replaced by the + operator. Otherwise, the result will be a pointer to an object or function indicated by its operand.

None of the paragraphs in the OP apply, as many have indicated. The meaning of something and its addresses are very different.

I would say that the absence of any restrictions and the invalidity of uninitialized values ​​that accept their address is allowed (due to the absence of a ban).

NOTE. We all know this very well, but it is very rare to find statements in these standards that clearly say "Yes, you can do it this way."

0
source

Source: https://habr.com/ru/post/1213622/


All Articles