Re: Question about declaring an array in the stack on runtime

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, 2023-07-15 at 18:43 +0800, James R T via Gcc-help wrote:
> Hi folks,
> 
> I hope that this is the correct mailing list to ask this question.
> 
> I have the following C code snippet:
> 
> ```c
> #include <stdio.h>
> 
> int main() {
>     unsigned int* arr;
>     int some_var = 7;
> 
>     if (some_var == 7) {
>         arr = (unsigned int[7]){9, 10, 11, 12, 13, 14, 15};
>     }
> 
>     printf("Value of arr:\n");
>     for (unsigned int i = 0; i < 7; i++) {
>         printf("%u ", arr[i]);
>     }
> 
>     return 0;
> }
> ```
> 
> I have included the relevant Godbolt link here:
> https://godbolt.org/z/b4rbn6eGT
> 
> I have a few questions related to this code snippet:
> 
> 1. Is the conditional assignment to `arr` considered undefined
> behavior?

No.  But the usage of arr[i] in the printf call is considered undefined
behavior.

> If it is, which exact clause of the C standard does this
> code snippet violate and why?

>From C23 6.5.2.5p5:

A compound literal provides an unnamed object whose value, type, storage
duration and other properties are as if given by the definition syntax
in the constraints; if the storage duration is automatic, the lifetime
of the instance of the unnamed object is the current execution of the
enclosing block.

And 6.2.4p2:

If an object is referred to outside of its lifetime, the behavior is
undefined.

And 6.8p1:

primary-block:
  compound-statement
  selection-statement
  iteration-statement

And 6.8p3:

A block is either a primary block, a secondary block, or the block
associated with a function definition;

So here the "enclosing block" is the if statement, after the if
statement the lifetime of the unnamed object provided by the compound
literal has ended, thus referring it in the printf call is undefined.

> 2. Regardless of whether this is UB or not, is it possible for GCC to
> also output a warning in `-O0` as in `-O2`? If the behavior changes
> across different optimization levels, it seems that it's worth a
> warning or two. It can be a different warning instead of
> `-Wdangling-pointer` since looking at the produced assembly code, GCC
> seems to simply optimize out the whole conditional assignment block in
> `-O2`. If it is UB, I understand that it is impossible to catch all
> UB, but I am just checking on whether it is possible to catch this
> specific one from GCC's perspective.

It's very difficult.  The emit of the warning depends on the optimizing
of the loop.  Without optimization the compiler doesn't even know the
loop will be iterated at least once, so there will be no warning is
produced at -O0.

> Just FYI, I have also tried using
> `-fsanitize=address` and `-fsanitize=undefined` and it seems that
> AddressSanitizer would throw a `stack-use-after-scope` error in GCC if
> `-fsanitize=address` is specified for both `-O0` and `-O2`, but not in
> Clang. `-fsanitize=undefined` does not seem to be able to detect
> anything.

It seems Clang completely unroll the loop and produced a series of
printf calls at -O2:

	leaq	.str.1(%rip), %rbx
	movq	%rbx, %rdi
	movl	$9, %esi
	xorl	%eax, %eax
	callq	printf@PLT
	movq	%rbx, %rdi
	movl	$10, %esi
	xorl	%eax, %eax
	callq	printf@PLT

... ...

So obviously -fsanitize=address won't work because there is no memory
access at all.  On the contrary, clang -fsanitize=address -O0 is able to
detect the issue.

And this is just completely out of the capability of -
fsanitize=undefined.  Despite the naming, -fsanitize=undefined can only
catch a *small* subset of undefined behaviors.

Generally sanitizers are useful tools, but not silver bullets.

> If the GCC maintainers consider this an acceptable proposal to add the
> warning, I am also willing to post a bug report and develop the
> corresponding patch for it, although I would appreciate some guidance
> since I am not very familiar with GCC's codebase.

I believe there has been a lot of duplicates about "no warnings at -O0".
And as I've said, these are very difficult to fix.  A lot of warnings
just inherently needs some information from the optimizer, or there will
be either too many false positives, or too many false negatives.  If you
need such warnings, you should enable the optimization.

-- 
Xi Ruoyao <xry111@xxxxxxxxxxx>
School of Aerospace Science and Technology, Xidian University




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux