Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #396062 > unrolled thread

On Undefined Behavior

Started byhighcrew <high.crew3868@fastmail.com>
First post2026-01-01 22:54 +0100
Last post2026-01-13 20:37 +0000
Articles 20 on this page of 113 — 18 participants

Back to article view | Back to comp.lang.c


Contents

  On Undefined Behavior highcrew <high.crew3868@fastmail.com> - 2026-01-01 22:54 +0100
    Re: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-02 00:26 +0200
      Re: On Undefined Behavior highcrew <high.crew3868@fastmail.com> - 2026-01-01 23:57 +0100
      Re: On Undefined Behavior Kaz Kylheku <046-301-5902@kylheku.com> - 2026-01-02 22:56 +0000
        Re: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-03 20:48 +0200
        Re: On Undefined Behavior highcrew <high.crew3868@fastmail.com> - 2026-01-04 14:38 +0100
          Re: On Undefined Behaviour Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-01-04 21:42 +0000
            Re: On Undefined Behaviour candycanearter07 <candycanearter07@candycanearter07.nomail.afraid> - 2026-01-07 06:40 +0000
          Re: On Undefined Behavior James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-01-04 16:58 -0500
            Re: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-05 08:49 +0100
    Re: On Undefined Behavior James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-01-01 17:49 -0500
    Re: On Undefined Behavior antispam@fricas.org (Waldek Hebisch) - 2026-01-02 05:53 +0000
      Re: On Undefined Behavior highcrew <high.crew3868@fastmail.com> - 2026-01-02 17:38 +0100
        Re: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-03 13:30 +0100
    Re: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-02 10:31 +0100
      Re: On Undefined Behavior highcrew <high.crew3868@fastmail.com> - 2026-01-02 17:51 +0100
        Re: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-03 13:42 +0100
          Re: On Undefined Behavior highcrew <high.crew3868@fastmail.com> - 2026-01-03 14:42 +0100
            Re: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-03 17:51 +0100
              Re: On Undefined Behavior highcrew <high.crew3868@fastmail.com> - 2026-01-04 00:20 +0100
    Re: On Undefined Behavior Kaz Kylheku <046-301-5902@kylheku.com> - 2026-01-02 22:52 +0000
      Re: On Undefined Behavior highcrew <high.crew3868@fastmail.com> - 2026-01-03 23:47 +0100
        Re: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-04 12:58 +0100
    Re: On Undefined Behavior Andrey Tarasevich <noone@noone.net> - 2026-01-03 07:53 -0800
      Re: On Undefined Behavior highcrew <high.crew3868@fastmail.com> - 2026-01-04 00:15 +0100
        NULL dereference in embedded [was: On Undefined Behavior] highcrew <high.crew3868@fastmail.com> - 2026-01-04 00:25 +0100
          Re: NULL dereference in embedded [was: On Undefined Behavior] James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-01-03 18:59 -0500
            Re: NULL dereference in embedded [was: On Undefined Behavior] scott@slp53.sl.home (Scott Lurndal) - 2026-01-04 15:51 +0000
              Re: NULL dereference in embedded [was: On Undefined Behavior] David Brown <david.brown@hesbynett.no> - 2026-01-05 08:55 +0100
          Re: NULL dereference in embedded [was: On Undefined Behavior] Andrey Tarasevich <noone@noone.net> - 2026-01-03 17:24 -0800
            Re: NULL dereference in embedded [was: On Undefined Behavior] Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-01-04 02:19 +0000
              Re: NULL dereference in embedded [was: On Undefined Behavior] James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-01-03 21:31 -0500
                Re: NULL dereference in embedded [was: On Undefined Behavior] Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-01-04 04:52 +0000
                  Re: NULL dereference in embedded [was: On Undefined Behavior] James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-01-04 13:00 -0500
                    Re: NULL dereference in embedded [was: On Undefined Behavior] Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-01-04 21:22 +0000
                      Re: NULL dereference in embedded [was: On Undefined Behavior] James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-01-04 16:53 -0500
                        Re: NULL dereference in embedded [was: On Undefined Behavior] Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-01-05 00:16 +0000
                          Re: NULL dereference in embedded [was: On Undefined Behavior] James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-01-05 06:41 -0500
                    Re: NULL dereference in embedded [was: On Undefined Behavior] David Brown <david.brown@hesbynett.no> - 2026-01-05 09:07 +0100
              Re: NULL dereference in embedded [was: On Undefined Behavior] scott@slp53.sl.home (Scott Lurndal) - 2026-01-04 15:56 +0000
            Re: NULL dereference in embedded [was: On Undefined Behavior] Andrey Tarasevich <noone@noone.net> - 2026-01-03 18:44 -0800
          Re: NULL dereference in embedded [was: On Undefined Behavior] David Brown <david.brown@hesbynett.no> - 2026-01-04 17:16 +0100
            Re: NULL dereference in embedded [was: On Undefined Behavior] antispam@fricas.org (Waldek Hebisch) - 2026-01-06 13:08 +0000
              Re: NULL dereference in embedded [was: On Undefined Behavior] Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-01-06 21:59 +0000
              Re: NULL dereference in embedded [was: On Undefined Behavior] Andrey Tarasevich <noone@noone.net> - 2026-01-07 20:48 -0800
                Re: NULL dereference in embedded [was: On Undefined Behavior] Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-01-08 23:56 +0000
    Re: On Undefined Behavior Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-01-03 23:14 +0000
    Re: On Undefined Behavior "Paul J. Lucas" <paul@lucasmail.org> - 2026-01-03 17:10 -0800
      Re: On Undefined Behavior highcrew <high.crew3868@fastmail.com> - 2026-01-04 12:51 +0100
        Re: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-05 15:39 +0100
          Re: On Undefined Behavior "Paul J. Lucas" <paul@lucasmail.org> - 2026-01-06 18:08 -0800
            Re: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-07 11:25 +0100
            Re: On Undefined Behavior James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-01-07 06:31 -0500
            Re: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-07 14:10 +0200
    Re: On Undefined Behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-01-09 01:42 -0800
      Re: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-09 14:36 +0200
        Re: On Undefined Behavior Kaz Kylheku <046-301-5902@kylheku.com> - 2026-01-09 20:14 +0000
          Re: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-10 18:19 +0200
          Re: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-10 18:41 +0200
            Re: On Undefined Behavior Kaz Kylheku <046-301-5902@kylheku.com> - 2026-01-13 23:31 +0000
              Re: On Undefined Behavior antispam@fricas.org (Waldek Hebisch) - 2026-01-14 03:57 +0000
              Re: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-14 10:47 +0200
              Re: On Undefined Behavior Tristan Wibberley <tristan.wibberley+netnews2@alumni.manchester.ac.uk> - 2026-01-14 14:49 +0000
          Re: On Undefined Behavior Tristan Wibberley <tristan.wibberley+netnews2@alumni.manchester.ac.uk> - 2026-01-10 17:08 +0000
        Re: On Undefined Behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-01-11 11:48 -0800
          Re: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-11 22:52 +0200
            Re: On Undefined Behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-01-11 22:53 -0800
              Re: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-12 11:44 +0200
                Re: On Undefined Behavior "James Russell Kuyper Jr." <jameskuyper@alumni.caltech.edu> - 2026-01-12 20:29 -0500
            Re: On Undefined Behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-02-03 05:29 -0800
    Re: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-09 15:54 +0200
      Re: On Undefined Behavior wij <wyniijj5@gmail.com> - 2026-01-10 00:08 +0800
    UB or not UB? was: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-12 16:28 +0200
      Re: UB or not UB? was: On Undefined Behavior bart <bc@freeuk.com> - 2026-01-12 15:58 +0000
        Re: UB or not UB? was: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-12 20:08 +0200
          Re: UB or not UB? was: On Undefined Behavior scott@slp53.sl.home (Scott Lurndal) - 2026-01-12 20:02 +0000
            Re: UB or not UB? was: On Undefined Behavior "James Russell Kuyper Jr." <jameskuyper@alumni.caltech.edu> - 2026-01-12 21:09 -0500
              Re: UB or not UB? was: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-13 11:31 +0200
                Re: UB or not UB? was: On Undefined Behavior "James Russell Kuyper Jr." <jameskuyper@alumni.caltech.edu> - 2026-01-13 22:21 -0500
          Re: UB or not UB? was: On Undefined Behavior "James Russell Kuyper Jr." <jameskuyper@alumni.caltech.edu> - 2026-01-13 22:19 -0500
            Re: UB or not UB? was: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-14 09:35 +0100
              Re: UB or not UB? was: On Undefined Behavior antispam@fricas.org (Waldek Hebisch) - 2026-01-14 17:23 +0000
                Re: UB or not UB? was: On Undefined Behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-01-14 12:53 -0800
              Re: UB or not UB? was: On Undefined Behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-01-14 14:43 -0800
                Re: UB or not UB? was: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-15 11:45 +0100
                  Re: UB or not UB? was: On Undefined Behavior James Kuyper <jameskuyper@alumni.caltech.edu> - 2026-01-15 06:16 -0500
                  Re: UB or not UB? was: On Undefined Behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-01-15 04:04 -0800
                    Re: UB or not UB? was: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-15 13:56 +0100
                    Re: UB or not UB? was: On Undefined Behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-02-03 05:34 -0800
                  Re: UB or not UB? was: On Undefined Behavior scott@slp53.sl.home (Scott Lurndal) - 2026-01-15 15:10 +0000
                    Re: UB or not UB? was: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-15 16:23 +0100
        Re: UB or not UB? was: On Undefined Behavior Tristan Wibberley <tristan.wibberley+netnews2@alumni.manchester.ac.uk> - 2026-01-13 21:54 +0000
          Re: UB or not UB? was: On Undefined Behavior "James Russell Kuyper Jr." <jameskuyper@alumni.caltech.edu> - 2026-01-13 21:58 -0500
            Re: UB or not UB? was: On Undefined Behavior Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2026-01-13 22:02 -0800
              Re: UB or not UB? was: On Undefined Behavior Tristan Wibberley <tristan.wibberley+netnews2@alumni.manchester.ac.uk> - 2026-01-14 14:24 +0000
                Re: UB or not UB? was: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-14 16:48 +0200
      Re: UB or not UB? was: On Undefined Behavior Andrey Tarasevich <noone@noone.net> - 2026-01-12 08:03 -0800
        Re: UB or not UB? was: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-12 19:36 +0200
          Re: UB or not UB? was: On Undefined Behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-01-12 12:03 -0800
            Re: UB or not UB? was: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-12 22:41 +0200
              Re: UB or not UB? was: On Undefined Behavior David Brown <david.brown@hesbynett.no> - 2026-01-13 09:12 +0100
              Re: UB or not UB? was: On Undefined Behavior pa@see.signature.invalid (Pierre Asselin) - 2026-01-13 20:19 +0000
              Re: UB or not UB? was: On Undefined Behavior "James Russell Kuyper Jr." <jameskuyper@alumni.caltech.edu> - 2026-01-13 22:20 -0500
              Re: UB or not UB? was: On Undefined Behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-02-03 21:53 -0800
            Re: UB or not UB? was: On Undefined Behavior Tristan Wibberley <tristan.wibberley+netnews2@alumni.manchester.ac.uk> - 2026-01-13 23:53 +0000
              Re: UB or not UB? was: On Undefined Behavior Tristan Wibberley <tristan.wibberley+netnews2@alumni.manchester.ac.uk> - 2026-01-14 08:06 +0000
          Re: UB or not UB? was: On Undefined Behavior Andrey Tarasevich <noone@noone.net> - 2026-01-13 08:11 -0800
            Re: UB or not UB? was: On Undefined Behavior "James Russell Kuyper Jr." <jameskuyper@alumni.caltech.edu> - 2026-01-13 22:10 -0500
            Re: UB or not UB? was: On Undefined Behavior Tim Rentsch <tr.17687@z991.linuxsc.com> - 2026-03-01 22:53 -0800
          Re: UB or not UB? was: On Undefined Behavior "James Russell Kuyper Jr." <jameskuyper@alumni.caltech.edu> - 2026-01-13 22:20 -0500
      Re: UB or not UB? was: On Undefined Behavior "James Russell Kuyper Jr." <jameskuyper@alumni.caltech.edu> - 2026-01-12 20:35 -0500
        Re: UB or not UB? was: On Undefined Behavior Michael S <already5chosen@yahoo.com> - 2026-01-13 11:07 +0200
    Re: On Undefined Behavior Tristan Wibberley <tristan.wibberley+netnews2@alumni.manchester.ac.uk> - 2026-01-13 20:37 +0000

Page 3 of 6 — ← Prev page 1 2 [3] 4 5 6  Next page →


#396136 — Re: NULL dereference in embedded [was: On Undefined Behavior]

FromAndrey Tarasevich <noone@noone.net>
Date2026-01-03 18:44 -0800
SubjectRe: NULL dereference in embedded [was: On Undefined Behavior]
Message-ID<10jck5j$1n2aq$1@dont-email.me>
In reply to#396133
On Sat 1/3/2026 5:24 PM, Andrey Tarasevich wrote:
> On Sat 1/3/2026 3:25 PM, highcrew wrote:
>> On 1/4/26 12:15 AM, highcrew wrote:
>>> I have a horrible question now, but that's for a
>>> separate question...
>>
>> And the question is:
>>
>> Embedded systems.  Address 0x00000000 is mapped to the flash.
>> I want to assign a pointer to 0x00000000 and dereference it to
>> read the first word.
>> That's UB.
>>
>> How do I?
> 
> Well, the first question would be: what is the physical null pointer 
> representation in that C implementation on that embedded system?
> ...

Although, on the second thought, what I said above, while correct, is 
hardly relevant to the matter if using UB for optimizations.

UB-based optimizations rely on static analysis of the code during 
compilation. At that stage the platform-specific physical representation 
of null pointer plays no role at all. The only thing that matters is the 
ability of the compiler to identify and track _logical_ null pointers 
through the program. E.g. for the compiler

   int *p = 0;

is always a null pointer. And

   if (p != 0)

always checks pointer `p` for being null. The actual physical 
representation of `p` does not come into the picture at all.

In that case the key moment here is that only compile-time zero (i.e. 
integral constant expression zero) can be interpreted as a null pointer. 
A run-time zero cannot be.

And the only issue that remains is your original request "I want to 
assign a pointer to 0x00000000 and dereference it to read the first 
word". Well, firstly, the language does not offer you any 
standard-defined features for accessing specific addresses. But in 
real-life it is usually done through explicitly converting an integer 
address to a pointer type. Since

   int *p = 0;

has a reserved meaning and will not generally work as intended, one 
possible workaround would be

   uintptr_t a = 0;
   int *p = (int *) a;

In the above case `p` will not be seen by the compiler as a logical null 
pointer.

This is actually covered by the FAQ: https://c-faq.com/null/accessloc0.html

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#396145 — Re: NULL dereference in embedded [was: On Undefined Behavior]

FromDavid Brown <david.brown@hesbynett.no>
Date2026-01-04 17:16 +0100
SubjectRe: NULL dereference in embedded [was: On Undefined Behavior]
Message-ID<10je3om$24s3l$1@dont-email.me>
In reply to#396127
On 04/01/2026 00:25, highcrew wrote:
> On 1/4/26 12:15 AM, highcrew wrote:
>> I have a horrible question now, but that's for a
>> separate question...
> 
> And the question is:
> 
> Embedded systems.  Address 0x00000000 is mapped to the flash.
> I want to assign a pointer to 0x00000000 and dereference it to
> read the first word.
> That's UB.
> 
> How do I?
> 
> Now I guess that an embedded compiler targeting that certain
> architecture where dereferencing 0 makes sense will not treat
> it as UB.  But it is for sure a weird corner case.
> 

There are some common misconceptions about null pointers in C.  A "null 
pointer" is the result of converting a "null pointer constant", or 
another "null pointer", to a pointer type.  A null pointer constant is 
either an integer constant expression with the value 0 (such as the 
constant 0, or "1 - 1"), or "nullptr" in C23.  You can use "NULL" from 
<stddef.h> as a null pointer constant.

So if you write "int * p = 0;", then "p" holds a null pointer.  If you 
write "int * p = (int *) sizeof(*p); p--;" then "p" does not hold a null 
pointer, even though it will hold the value "0".

On virtually all real-world systems, including all embedded systems I 
have ever known (and that's quite a few), null pointers correspond to 
the address 0.  But that does not mean that dereferencing a pointer 
whose value is 0 is necessarily UB.

And even when dereferencing a pointer /is/ UB, a compiler can handle it 
as defined if it wants.

I think that if you have a microcontroller with code at address 0, and a 
pointer of some object type (say, "const uint8_t * p" or "const uint32_t 
* p") holding the address 0, then using that to read the flash at that 
address is UB.  But it is not UB because "p" holds a null pointer - it 
may or may not be a null pointer.  It is UB because "p" does not point 
to an object.

In practice, I have never seen an embedded compiler fail to do the 
expected thing when reading flash from address 0.  (Typical use-cases 
are for doing CRC checks or signature checks on code, or for reading the 
initial stack pointer value or reset vector of the code.)  If you want 
to be more confident, use a pointer to volatile type.

[toc] | [prev] | [next] | [standalone]


#396205 — Re: NULL dereference in embedded [was: On Undefined Behavior]

Fromantispam@fricas.org (Waldek Hebisch)
Date2026-01-06 13:08 +0000
SubjectRe: NULL dereference in embedded [was: On Undefined Behavior]
Message-ID<10jj1h7$1an77$2@paganini.bofh.team>
In reply to#396145
David Brown <david.brown@hesbynett.no> wrote:
> On 04/01/2026 00:25, highcrew wrote:
>> On 1/4/26 12:15 AM, highcrew wrote:
>>> I have a horrible question now, but that's for a
>>> separate question...
>> 
>> And the question is:
>> 
>> Embedded systems.  Address 0x00000000 is mapped to the flash.
>> I want to assign a pointer to 0x00000000 and dereference it to
>> read the first word.
>> That's UB.
>> 
>> How do I?
>> 
>> Now I guess that an embedded compiler targeting that certain
>> architecture where dereferencing 0 makes sense will not treat
>> it as UB.  But it is for sure a weird corner case.
>> 
> 
> There are some common misconceptions about null pointers in C.  A "null 
> pointer" is the result of converting a "null pointer constant", or 
> another "null pointer", to a pointer type.  A null pointer constant is 
> either an integer constant expression with the value 0 (such as the 
> constant 0, or "1 - 1"), or "nullptr" in C23.  You can use "NULL" from 
> <stddef.h> as a null pointer constant.
> 
> So if you write "int * p = 0;", then "p" holds a null pointer.  If you 
> write "int * p = (int *) sizeof(*p); p--;" then "p" does not hold a null 
> pointer, even though it will hold the value "0".
> 
> On virtually all real-world systems, including all embedded systems I 
> have ever known (and that's quite a few), null pointers correspond to 
> the address 0.  But that does not mean that dereferencing a pointer 
> whose value is 0 is necessarily UB.
> 
> And even when dereferencing a pointer /is/ UB, a compiler can handle it 
> as defined if it wants.
> 
> I think that if you have a microcontroller with code at address 0, and a 
> pointer of some object type (say, "const uint8_t * p" or "const uint32_t 
> * p") holding the address 0, then using that to read the flash at that 
> address is UB.  But it is not UB because "p" holds a null pointer - it 
> may or may not be a null pointer.  It is UB because "p" does not point 
> to an object.
> 
> In practice, I have never seen an embedded compiler fail to do the 
> expected thing when reading flash from address 0.  (Typical use-cases 
> are for doing CRC checks or signature checks on code, or for reading the 
> initial stack pointer value or reset vector of the code.)  If you want 
> to be more confident, use a pointer to volatile type.

For curiosity I tried the following:

#include <stdint.h>

uint32_t
read_at0(uint32_t * p) {
    if (!p) {
        return *p;
    } else {
        return 0;
    }
}

that is we read trough a pointer only when it is a null pointer.
Using gcc-12 with command line:

arm-none-eabi-gcc -O3 -fverbose-asm -fno-builtin -Wall -g  -mthumb -mcpu=cortex-m3 -c ts_null.c

I get the following assembly:

00000000 <read_at0>:
   0:   b108            cbz     r0, 6 <read_at0+0x6>
   2:   2000            movs    r0, #0
   4:   4770            bx      lr
   6:   6803            ldr     r3, [r0, #0]
   8:   deff            udf     #255    @ 0xff
   a:   bf00            nop

So compiler generates actiual access, but then, instead of returning
the value it executes undefined opcode.  Without test for null
pointer I get simple access to memory.

So at least with gcc access works as long as compiler does not
know that it is accessing null pointer.  But if compiler can
infer that pointer is null generated code may do strange
things.

Putting volatile qualifier on p gives working code, but apparently
disables optimization.  Also, this looks fragile.  So if I needed
to access address 0 I probably would use assembly routine to do this.

-- 
                              Waldek Hebisch

[toc] | [prev] | [next] | [standalone]


#396233 — Re: NULL dereference in embedded [was: On Undefined Behavior]

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-01-06 21:59 +0000
SubjectRe: NULL dereference in embedded [was: On Undefined Behavior]
Message-ID<10jk0ks$65pd$1@dont-email.me>
In reply to#396205
On Tue, 6 Jan 2026 13:08:57 -0000 (UTC), Waldek Hebisch wrote:

> Putting volatile qualifier on p gives working code, but apparently
> disables optimization.  Also, this looks fragile.  So if I needed
> to access address 0 I probably would use assembly routine to do this.

Seems to be a fundamental C language limitation, wouldn’t you say?

[toc] | [prev] | [next] | [standalone]


#396293 — Re: NULL dereference in embedded [was: On Undefined Behavior]

FromAndrey Tarasevich <noone@noone.net>
Date2026-01-07 20:48 -0800
SubjectRe: NULL dereference in embedded [was: On Undefined Behavior]
Message-ID<10jncu3$17m7b$1@dont-email.me>
In reply to#396205
On Tue 1/6/2026 5:08 AM, Waldek Hebisch wrote:
> 
> I get the following assembly:
> 
> 00000000 <read_at0>:
>     0:   b108            cbz     r0, 6 <read_at0+0x6>
>     2:   2000            movs    r0, #0
>     4:   4770            bx      lr
>     6:   6803            ldr     r3, [r0, #0]
>     8:   deff            udf     #255    @ 0xff
>     a:   bf00            nop
> 
> So compiler generates actiual access, but then, instead of returning
> the value it executes undefined opcode.  Without test for null
> pointer I get simple access to memory.
> 

When it comes to invalid (or missing, in C++) `return` statements, GCC 
tends to adhere to a "punitive" approach in optimized code - it injects 
instructions to deliberately cause a crash/segfault in such cases.

Clang on the other hand tends to stick to the uniform approach based on 
the "UB cannot happen" methodology, i.e. your code sample would be 
translated under "p is never null" assumption, and the function will 
fold into a simple unconditional `return 0`.

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#396311 — Re: NULL dereference in embedded [was: On Undefined Behavior]

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-01-08 23:56 +0000
SubjectRe: NULL dereference in embedded [was: On Undefined Behavior]
Message-ID<10jpg70$1u9fo$3@dont-email.me>
In reply to#396293
On Wed, 7 Jan 2026 20:48:03 -0800, Andrey Tarasevich wrote:

> When it comes to invalid (or missing, in C++) `return` statements,
> GCC tends to adhere to a "punitive" approach in optimized code - it
> injects instructions to deliberately cause a crash/segfault in such
> cases.
>
> Clang on the other hand tends to stick to the uniform approach based
> on the "UB cannot happen" methodology, i.e. your code sample would
> be translated under "p is never null" assumption, and the function
> will fold into a simple unconditional `return 0`.

Which one is more likely to lead to unexpected, hard-to-debug results?

[toc] | [prev] | [next] | [standalone]


#396124

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-01-03 23:14 +0000
Message-ID<10jc7sp$1joop$3@dont-email.me>
In reply to#396062
On Thu, 1 Jan 2026 22:54:05 +0100, highcrew wrote:

> Well, this is *obviously* wrong.

I think it’s quite a clever way for the compiler to say “fuck you” to
the programmer who wrote that. ;)

[toc] | [prev] | [next] | [standalone]


#396132

From"Paul J. Lucas" <paul@lucasmail.org>
Date2026-01-03 17:10 -0800
Message-ID<10jcem1$1lun2$1@dont-email.me>
In reply to#396062
On 1/1/26 1:54 PM, highcrew wrote:

> For the lazy, I report it here:
> 
>    int table[4] = {0};
>    int exists_in_table(int v)
>    {
>        // return true in one of the first 4 iterations
>        // or UB due to out-of-bounds access
>        for (int i = 0; i <= 4; i++) {
>            if (table[i] == v) return 1;
>        }
>        return 0;
>    }

This particular example is explained is several places, e.g.:

https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=633

Perhaps a slightly better explanation of the same example:

https://medium.com/@pauljlucas/undefined-behavior-in-c-and-c-f30844f20e2a

- Paul

[toc] | [prev] | [next] | [standalone]


#396140

Fromhighcrew <high.crew3868@fastmail.com>
Date2026-01-04 12:51 +0100
Message-ID<10jdk7u$1vb1h$1@dont-email.me>
In reply to#396132
On 1/4/26 2:10 AM, Paul J. Lucas wrote:
> This particular example is explained is several places, e.g.:
> 
> https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=633
> 
> Perhaps a slightly better explanation of the same example:
> 
> https://medium.com/@pauljlucas/undefined-behavior-in-c-and-c-f30844f20e2a
> 
> - Paul

Hey, thanks for the pointers.
I found the second a really good write up!

-- 
High Crew

[toc] | [prev] | [next] | [standalone]


#396174

FromDavid Brown <david.brown@hesbynett.no>
Date2026-01-05 15:39 +0100
Message-ID<10jgif0$2ur09$1@nntp.eternal-september.org>
In reply to#396140
On 04/01/2026 12:51, highcrew wrote:
> On 1/4/26 2:10 AM, Paul J. Lucas wrote:
>> This particular example is explained is several places, e.g.:
>>
>> https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=633
>>

At a cursory read, that article looks okay.  The lesson to learn is 
"look before you leap" - don't use data if you are not sure it is valid, 
and certainly don't add new uses of the data (such as debug prints) just 
before validity checks!

It does, however, perpetuate the myth that there is a clear distinction 
between "classical compilers" or "non-optimising compilers" and 
"optimising compilers".  That is not true - for any two standards 
conforming compilers (or selection of flags for the same compiler), the 
same source code is equally defined or undefined.  Source code with UB 
has UB whether it is "optimised" or not, though the colour of the 
resulting nasal daemons may vary.


>> Perhaps a slightly better explanation of the same example:
>>
>> https://medium.com/@pauljlucas/undefined-behavior-in-c-and-c-f30844f20e2a
>>

That one starts off with a bit of a jumble of misconceptions.


To start with, "undefined behaviour" does not exist because of 
compatibility issues or the merging of different C variations into one 
standard C.  It is a fundamental principle in programming because many 
computing functions are, mathematically, partial functions - they can 
only give a sensible defined result for some inputs.  While it can 
sometimes be possible to verify the validity of inputs, it is often 
infeasible or at least very costly, especially in non-managed (compiled) 
languages.  Pointer dereference, for example, only has defined behaviour 
if the pointer points to a valid object - otherwise the result is 
meaningless (even if some assembly code can be generated).  Garbage in, 
garbage out - see the Babbage quotation.

The C standard is simply somewhat unusual in that it is more explicit 
about UB than many languages' documentation.  And being a language 
intended for maximally efficient code, C leaves a number of things as UB 
where other languages might throw an exception or have other error handling.

The definition given for "implementation defined behaviour" and 
"unspecified behaviour" is poor.  (IMHO the comp.lang.c FAQ is 
inaccurate here.)  In particular, "unspecified behaviour" does not need 
to be consistent.  For example, the order of evaluation of function 
arguments is unspecified, and can be done in different orders at 
different call sites - even in identical source code.  It can even be 
re-ordered between different invocations of the same code - perhaps due 
to complicated inter-procedural optimisations, inlining, code cloning, 
and constant propagation.

It then goes on to say that the order of evaluation of the operands of 
"+" are implementation defined, when it is in fact a good example of 
unspecified behaviour that is /not/ implementation defined.

Implementation defined behaviour is /not/ "bad" - pretty much all 
programs rely on implementation-defined behaviour such as the size of 
"int", character sets used, etc.  Relying on implementation-defined 
behaviour reduces the portability of code, but that is not necessary a 
bad thing.

And while it is true that UB is "worse" than either 
implementation-defined behaviour or unspecified behaviour, it is not for 
either of the reasons given.  The *nix program "date" does not need to 
contain UB in order to produce different results at different times.


The examples of UB, and the consequences of them, are better.

It also makes the mistake common in discussions of UB optimisations of 
concluding that the optimisation makes the code "wrong".  Optimisations, 
such as the example of the "assign_not_null" function, are "logically 
valid" and /correct/ from the given source code.  Optimisations have not 
made the code "wrong", nor has the compiler.  The source code is correct 
for a given validity subset of its parameter types, and the object code 
is correct for that same subset.  If the source code is intended to work 
over a wider range of inputs, then it is the source code that is wrong - 
not the optimiser or the optimised code.


>> - Paul
> 
> Hey, thanks for the pointers.
> I found the second a really good write up!
> 

I've seen worse, but it could be better.

[toc] | [prev] | [next] | [standalone]


#396244

From"Paul J. Lucas" <paul@lucasmail.org>
Date2026-01-06 18:08 -0800
Message-ID<10jkf6o$ahhq$1@dont-email.me>
In reply to#396174
On 1/5/26 6:39 AM, David Brown wrote:
> On 04/01/2026 12:51, highcrew wrote:
>> On 1/4/26 2:10 AM, Paul J. Lucas wrote:
>>> Perhaps a slightly better explanation of the same example:
>>>
>>> https://medium.com/@pauljlucas/undefined-behavior-in-c-and-c- 
>>> f30844f20e2a
> 
> That one starts off with a bit of a jumble of misconceptions.
> 
> 
> To start with, "undefined behaviour" does not exist because of 
> compatibility issues or the merging of different C variations into one 
> standard C.

...

> The C standard is simply somewhat unusual in that it is more explicit 
> about UB than many languages' documentation.  And being a language 
> intended for maximally efficient code, C leaves a number of things as UB 
> where other languages might throw an exception or have other error 
> handling.

Other languages had the luxury of doing that.  As the article pointed
out, C had existed for over a decade before the standard and there were
many programs in the wild that relied on their existing behaviors.  By
this time, the C standard could not retroactively "throw an exception or
have other error handling" since it would have broken those programs, so
it _had_ to leave many things as UB explicitly.  Hence, the article
isn't wrong.

> Implementation defined behaviour is /not/ "bad" - pretty much all 
> programs rely on implementation-defined behaviour such as the size of 
> "int", character sets used, etc.  Relying on implementation-defined 
> behaviour reduces the portability of code, but that is not necessary a 
> bad thing.

It's "bad" if a naive programmer isn't aware it's implementation defined
and just assumes it's defined however it's defined on his machine.

> And while it is true that UB is "worse" than either implementation- 
> defined behaviour or unspecified behaviour, it is not for either of the 
> reasons given.  The *nix program "date" does not need to contain UB in 
> order to produce different results at different times.

Sure, but the article didn't mean such cases. It meant for cases like
incrementing a signed integer past INT_MAX.  A program could
legitimately give different answers for the same line of code at
different times.

> It also makes the mistake common in discussions of UB optimisations of 
> concluding that the optimisation makes the code "wrong".  Optimisations, 
> such as the example of the "assign_not_null" function, are "logically 
> valid" and /correct/ from the given source code.  Optimisations have not 
> made the code "wrong", nor has the compiler.  The source code is correct 
> for a given validity subset of its parameter types, and the object code 
> is correct for that same subset.  If the source code is intended to work 
> over a wider range of inputs, then it is the source code that is wrong - 
> not the optimiser or the optimised code.
What the author meant is that optimization can make UB manifest more
bizarrely in ways than not optimizing wouldn't.  Code that contains UB 
is always wrong.

- Paul

[toc] | [prev] | [next] | [standalone]


#396252

FromDavid Brown <david.brown@hesbynett.no>
Date2026-01-07 11:25 +0100
Message-ID<10jlcbf$ib5s$1@dont-email.me>
In reply to#396244
On 07/01/2026 03:08, Paul J. Lucas wrote:
> On 1/5/26 6:39 AM, David Brown wrote:
>> On 04/01/2026 12:51, highcrew wrote:
>>> On 1/4/26 2:10 AM, Paul J. Lucas wrote:
>>>> Perhaps a slightly better explanation of the same example:
>>>>
>>>> https://medium.com/@pauljlucas/undefined-behavior-in-c-and-c- 
>>>> f30844f20e2a
>>
>> That one starts off with a bit of a jumble of misconceptions.
>>
>>
>> To start with, "undefined behaviour" does not exist because of 
>> compatibility issues or the merging of different C variations into one 
>> standard C.
> 
> ...
> 
>> The C standard is simply somewhat unusual in that it is more explicit 
>> about UB than many languages' documentation.  And being a language 
>> intended for maximally efficient code, C leaves a number of things as 
>> UB where other languages might throw an exception or have other error 
>> handling.
> 
> Other languages had the luxury of doing that.  As the article pointed
> out, C had existed for over a decade before the standard and there were
> many programs in the wild that relied on their existing behaviors.  By
> this time, the C standard could not retroactively "throw an exception or
> have other error handling" since it would have broken those programs, so
> it _had_ to leave many things as UB explicitly.  Hence, the article
> isn't wrong.
> 

UB as a /concept/ does not exist because of compatibility issues. 
Certain particular things may have been declared UB in C because of 
compatibility between different existing compilers or different targets 
(though it is more common for such things to be declared 
"implementation-defined" rather than UB).  I am, however, having 
difficulty finding examples of that for run-time UB.  (There are plenty 
of situations where there is UB that could be identified at compile-time 
or link time, but the standard does not require toolchains to diagnose.)

The idea that something can be expressed in a programming language, 
without errors in syntax, but have no meaningful or correct behaviour, 
is not new, and not restricted to C.  UB in C is not different from 
asking for the square root of a negative number in the real domain, or 
asking a kid to add 3 and 4 using the fingers of one hand.


>> Implementation defined behaviour is /not/ "bad" - pretty much all 
>> programs rely on implementation-defined behaviour such as the size of 
>> "int", character sets used, etc.  Relying on implementation-defined 
>> behaviour reduces the portability of code, but that is not necessary a 
>> bad thing.
> 
> It's "bad" if a naive programmer isn't aware it's implementation defined
> and just assumes it's defined however it's defined on his machine.
> 

Sure.  But that applies to all portability issues - people make all 
sorts of assumptions about the system their code will be used on, of 
which the implementation-defined aspects of C are only a small part.

>> And while it is true that UB is "worse" than either implementation- 
>> defined behaviour or unspecified behaviour, it is not for either of 
>> the reasons given.  The *nix program "date" does not need to contain 
>> UB in order to produce different results at different times.
> 
> Sure, but the article didn't mean such cases. 

If the author meant something different, he/she should have written 
something different.

> It meant for cases like
> incrementing a signed integer past INT_MAX.  A program could
> legitimately give different answers for the same line of code at
> different times.

It could also give different answers for unspecified behaviour :

	int first(void) { printf("1 "); return 1; }
	int second(void) { printf("2 "); return 2; }

	int x = first() + second();

The evaluation order of the operands of the addition - and therefore the 
order of the debug prints, is unspecified.  Not only is the order not 
something specified by the C standards, but it is not something that 
needs to be consistent even between different runs of the same code.

So this "giving different answers" is not something special about UB.

> 
>> It also makes the mistake common in discussions of UB optimisations of 
>> concluding that the optimisation makes the code "wrong".  
>> Optimisations, such as the example of the "assign_not_null" function, 
>> are "logically valid" and /correct/ from the given source code.  
>> Optimisations have not made the code "wrong", nor has the compiler.  
>> The source code is correct for a given validity subset of its 
>> parameter types, and the object code is correct for that same subset.  
>> If the source code is intended to work over a wider range of inputs, 
>> then it is the source code that is wrong - not the optimiser or the 
>> optimised code.
> What the author meant is that optimization can make UB manifest more
> bizarrely in ways than not optimizing wouldn't.  Code that contains UB 
> is always wrong.
> 

If the author meant something different from what he wrote, it would 
have been better if he wrote what he meant.

Yes, in practice you /can/ get a wider variety of strange results from 
code with UB if you use a highly optimising compiler compared to a 
simple compiler.  But there are no guarantees there - you can get 
strange results from UB when not optimising, and perhaps enabling 
optimisation will give you simple and more consistent results (possibly 
the results you expected, possibly not).

It is fine to tell people about some of the strange possibilities that 
can occur when you have UB.  But anything that even sounds vaguely like 
a suggestion that you can mitigate the dangers of UB by disabling 
optimisation is bad.  Far too many C programmers believe that.

[toc] | [prev] | [next] | [standalone]


#396256

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2026-01-07 06:31 -0500
Message-ID<10jlg6k$3jbe4$7@dont-email.me>
In reply to#396244
On 2026-01-06 21:08, Paul J. Lucas wrote:
...
> What the author meant is that optimization can make UB manifest more
> bizarrely in ways than not optimizing wouldn't.  Code that contains UB 
> is always wrong.

"undefined behavior" is defined by the C standard as referring to
behavior on which "this international standard imposes no requirements".
It remains UB even if some other document imposes requirements on the
behavior. In particular, if a given implementation implements an
extension that gives defined behavior to code that the C standard does
not, it's still UB, but it's entirely reasonable for users of that
implementation to decide they want to use that extension.

[toc] | [prev] | [next] | [standalone]


#396259

FromMichael S <already5chosen@yahoo.com>
Date2026-01-07 14:10 +0200
Message-ID<20260107141046.0000165f@yahoo.com>
In reply to#396244
On Tue, 6 Jan 2026 18:08:22 -0800
"Paul J. Lucas" <paul@lucasmail.org> wrote:

> 
> Other languages had the luxury of doing that.  As the article pointed
> out, C had existed for over a decade before the standard and there
> were many programs in the wild that relied on their existing
> behaviors.  By this time, the C standard could not retroactively
> "throw an exception or have other error handling" since it would have
> broken those programs, so it _had_ to leave many things as UB
> explicitly.  Hence, the article isn't wrong.
> 

O.T.
Rust exists for 13 years without standard. Did not prevent it from
becoming more hyped than Ada in her heyday.

Go exists without standard for how long? 20 years?
But at least in case of Go there exists official specification that
is not rewritten on every Tuesday.

[toc] | [prev] | [next] | [standalone]


#396318

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2026-01-09 01:42 -0800
Message-ID<86ms2nm89u.fsf@linuxsc.com>
In reply to#396062
highcrew <high.crew3868@fastmail.com> writes:

> Hello,
>
> While I consider myself reasonably good as C programmer, I still
> have difficulties in understanding undefined behavior.
> I wonder if anyone in this NG could help me.
>
> Let's take an example.  There's plenty here:
> https://en.cppreference.com/w/c/language/behavior.html
> So let's focus on https://godbolt.org/z/48bn19Tsb
>
> For the lazy, I report it here:
>
>   int table[4] = {0};
>   int exists_in_table(int v)
>   {
>       // return true in one of the first 4 iterations
>       // or UB due to out-of-bounds access
>       for (int i = 0; i <= 4; i++) {
>           if (table[i] == v) return 1;
>       }
>       return 0;
>   }
>
> This is compiled (with no warning whatsoever) into:
>
>   exists_in_table:
>           mov     eax, 1
>           ret
>   table:
>           .zero   16
>
>
> Well, this is *obviously* wrong.  And sure, so is the original code,
> but I find it hard to think that the compiler isn't able to notice it,
> given that it is even "exploiting" it to produce very efficient code.
>
> I understand the formalism:  the resulting assembly is formally
> "correct", in that UB implies that anything can happen.
> Yet I can't think of any situation where the resulting assembly
> could be considered sensible.  The compiled function will
> basically return 1 for any input, and the final program will be
> buggy.
>
> Wouldn't it be more sensible to have a compilation error, or
> at least a warning?  The compiler will be happy even with -Wall -Wextra
> -Werror.
>
> There's plenty of documentation, articles and presentations that
> explain how this can make very efficient code... but nothing
> will answer this question:  do I really want to be efficiently
> wrong?
>
> I mean, yes I would find the problem, thanks to my 100% coverage
> unit testing, but couldn't the compiler give me a hint?
>
> Could someone drive me into this reasoning?  I know there is a lot of
> thinking behind it, yet everything seems to me very incorrect!
> I'm in deep cognitive dissonance here! :)  Help!

The important thing to realize is that the fundamental issue here
is not a technical question but a social question.  In effect what
you are asking is "why doesn't gcc (or clang, or whatever) do what
I want or expect?".  The answer is different people want or expect
different things.  For some people the behavior described is
egregiously wrong and must be corrected immediately.  For other
people the compiler is acting just as they think it should,
nothing to see here, just fix the code and move on to the next
bug.  Different people have different priorities.

After observing that, I think the right question is something like
"Given that compilers act in these surprising ways, how should I
protect my code so that it doesn't fall prey to the death-by-UB
syndrome, or what can I do to diagnose a possibly death-by-UB
situation when a strange bug crops up?"  I don't pretend to have
good answers to these questions.  The best advice I can give
(besides seeking help from others with more experience) is to be
persistent, and to realize that the skills needed for combating a
death-by-UB syndrome are rather different from the skills needed
for regular programming.  I have been in the situation of being
made responsible for finding and correcting a death-by-UB kind of
symptom, and what's worse in programming environment where I
didn't have a great deal of familiarity or experience.  Despite
those drawbacks the bug got diagnosed and fixed, and I attribute
that result mostly to tenacity and by being willing to consider
unusual or unfamiliar points of view.

[toc] | [prev] | [next] | [standalone]


#396320

FromMichael S <already5chosen@yahoo.com>
Date2026-01-09 14:36 +0200
Message-ID<20260109143647.0000372d@yahoo.com>
In reply to#396318
On Fri, 09 Jan 2026 01:42:53 -0800
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

> highcrew <high.crew3868@fastmail.com> writes:
> 
> > Hello,
> >
> > While I consider myself reasonably good as C programmer, I still
> > have difficulties in understanding undefined behavior.
> > I wonder if anyone in this NG could help me.
> >
> > Let's take an example.  There's plenty here:
> > https://en.cppreference.com/w/c/language/behavior.html
> > So let's focus on https://godbolt.org/z/48bn19Tsb
> >
> > For the lazy, I report it here:
> >
> >   int table[4] = {0};
> >   int exists_in_table(int v)
> >   {
> >       // return true in one of the first 4 iterations
> >       // or UB due to out-of-bounds access
> >       for (int i = 0; i <= 4; i++) {
> >           if (table[i] == v) return 1;
> >       }
> >       return 0;
> >   }
> >
> > This is compiled (with no warning whatsoever) into:
> >
> >   exists_in_table:
> >           mov     eax, 1
> >           ret
> >   table:
> >           .zero   16
> >
> >
> > Well, this is *obviously* wrong.  And sure, so is the original code,
> > but I find it hard to think that the compiler isn't able to notice
> > it, given that it is even "exploiting" it to produce very efficient
> > code.
> >
> > I understand the formalism:  the resulting assembly is formally
> > "correct", in that UB implies that anything can happen.
> > Yet I can't think of any situation where the resulting assembly
> > could be considered sensible.  The compiled function will
> > basically return 1 for any input, and the final program will be
> > buggy.
> >
> > Wouldn't it be more sensible to have a compilation error, or
> > at least a warning?  The compiler will be happy even with -Wall
> > -Wextra -Werror.
> >
> > There's plenty of documentation, articles and presentations that
> > explain how this can make very efficient code... but nothing
> > will answer this question:  do I really want to be efficiently
> > wrong?
> >
> > I mean, yes I would find the problem, thanks to my 100% coverage
> > unit testing, but couldn't the compiler give me a hint?
> >
> > Could someone drive me into this reasoning?  I know there is a lot
> > of thinking behind it, yet everything seems to me very incorrect!
> > I'm in deep cognitive dissonance here! :)  Help!  
> 
> The important thing to realize is that the fundamental issue here
> is not a technical question but a social question.  In effect what
> you are asking is "why doesn't gcc (or clang, or whatever) do what
> I want or expect?".  The answer is different people want or expect
> different things.  For some people the behavior described is
> egregiously wrong and must be corrected immediately.  For other
> people the compiler is acting just as they think it should,
> nothing to see here, just fix the code and move on to the next
> bug.  Different people have different priorities.
>

I have hard time imagining sort of people that would have objections in
case compiler generates the same code as today, but issues diagnostic.
Probably in the same style that it often produces in similar situations:
 warning: array subscript 4 is above array bounds of 'int[4]'
 [-Warray-bounds]

> After observing that, I think the right question is something like
> "Given that compilers act in these surprising ways, how should I
> protect my code so that it doesn't fall prey to the death-by-UB
> syndrome, or what can I do to diagnose a possibly death-by-UB
> situation when a strange bug crops up?"  I don't pretend to have
> good answers to these questions.  The best advice I can give
> (besides seeking help from others with more experience) is to be
> persistent, and to realize that the skills needed for combating a
> death-by-UB syndrome are rather different from the skills needed
> for regular programming.  I have been in the situation of being
> made responsible for finding and correcting a death-by-UB kind of
> symptom, and what's worse in programming environment where I
> didn't have a great deal of familiarity or experience.  Despite
> those drawbacks the bug got diagnosed and fixed, and I attribute
> that result mostly to tenacity and by being willing to consider
> unusual or unfamiliar points of view.

[toc] | [prev] | [next] | [standalone]


#396328

FromKaz Kylheku <046-301-5902@kylheku.com>
Date2026-01-09 20:14 +0000
Message-ID<20260109120633.815@kylheku.com>
In reply to#396320
On 2026-01-09, Michael S <already5chosen@yahoo.com> wrote:
> On Fri, 09 Jan 2026 01:42:53 -0800
> Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>
>> highcrew <high.crew3868@fastmail.com> writes:
>> 
>> > Hello,
>> >
>> > While I consider myself reasonably good as C programmer, I still
>> > have difficulties in understanding undefined behavior.
>> > I wonder if anyone in this NG could help me.
>> >
>> > Let's take an example.  There's plenty here:
>> > https://en.cppreference.com/w/c/language/behavior.html
>> > So let's focus on https://godbolt.org/z/48bn19Tsb
>> >
>> > For the lazy, I report it here:
>> >
>> >   int table[4] = {0};
>> >   int exists_in_table(int v)
>> >   {
>> >       // return true in one of the first 4 iterations
>> >       // or UB due to out-of-bounds access
>> >       for (int i = 0; i <= 4; i++) {
>> >           if (table[i] == v) return 1;
>> >       }
>> >       return 0;
>> >   }
>> >
>> > This is compiled (with no warning whatsoever) into:
>> >
>> >   exists_in_table:
>> >           mov     eax, 1
>> >           ret
>> >   table:
>> >           .zero   16
>> >
>> >
>> > Well, this is *obviously* wrong.  And sure, so is the original code,
>> > but I find it hard to think that the compiler isn't able to notice
>> > it, given that it is even "exploiting" it to produce very efficient
>> > code.
>> >
>> > I understand the formalism:  the resulting assembly is formally
>> > "correct", in that UB implies that anything can happen.
>> > Yet I can't think of any situation where the resulting assembly
>> > could be considered sensible.  The compiled function will
>> > basically return 1 for any input, and the final program will be
>> > buggy.
>> >
>> > Wouldn't it be more sensible to have a compilation error, or
>> > at least a warning?  The compiler will be happy even with -Wall
>> > -Wextra -Werror.
>> >
>> > There's plenty of documentation, articles and presentations that
>> > explain how this can make very efficient code... but nothing
>> > will answer this question:  do I really want to be efficiently
>> > wrong?
>> >
>> > I mean, yes I would find the problem, thanks to my 100% coverage
>> > unit testing, but couldn't the compiler give me a hint?
>> >
>> > Could someone drive me into this reasoning?  I know there is a lot
>> > of thinking behind it, yet everything seems to me very incorrect!
>> > I'm in deep cognitive dissonance here! :)  Help!  
>> 
>> The important thing to realize is that the fundamental issue here
>> is not a technical question but a social question.  In effect what
>> you are asking is "why doesn't gcc (or clang, or whatever) do what
>> I want or expect?".  The answer is different people want or expect
>> different things.  For some people the behavior described is
>> egregiously wrong and must be corrected immediately.  For other
>> people the compiler is acting just as they think it should,
>> nothing to see here, just fix the code and move on to the next
>> bug.  Different people have different priorities.
>>
>
> I have hard time imagining sort of people that would have objections in
> case compiler generates the same code as today, but issues diagnostic.

If false positives occur for the diagnostic frequently, there
will be legitimate complaint.

If there is only a simple switch for it, it will get turned off
and then it no longer serves its purpose of catching errors.

There are all kinds of optimizations compilers commonly do that could
also be erroneous situations. For instance, eliminating dead code.

  // code portable among several types of systems:

  switch (sizeof var) {
  case 2: ...
  case 4: ...
  case 8: ...
  }

sizeof var is a compile time constant expected to be 2, 4 or 8 bytes.
The other cases are unreachable code.

Suppose every time the compiler eliminates unreachable code, it
issues a diagnostic "foo.c:42: 3 lines of unreachable code removed".

That would be annoying when the programmer knows about dead code
elimination and is counting on it.

We also have to consider that not all code is written directly by hand.

Code generation techniques (including macros) can produce "weird" code
in some of their corner cases. The code is correct, and it would take
more complexity to identify those cases and generate more idiomatic
code; it is left to the compiler to clean up.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca

[toc] | [prev] | [next] | [standalone]


#396332

FromMichael S <already5chosen@yahoo.com>
Date2026-01-10 18:19 +0200
Message-ID<20260110181905.00000f0e@yahoo.com>
In reply to#396328
On Fri, 9 Jan 2026 20:14:04 -0000 (UTC)
Kaz Kylheku <046-301-5902@kylheku.com> wrote:

> On 2026-01-09, Michael S <already5chosen@yahoo.com> wrote:
> > On Fri, 09 Jan 2026 01:42:53 -0800
> > Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
> >  
> >> highcrew <high.crew3868@fastmail.com> writes:
> >>   
> >> > Hello,
> >> >
> >> > While I consider myself reasonably good as C programmer, I still
> >> > have difficulties in understanding undefined behavior.
> >> > I wonder if anyone in this NG could help me.
> >> >
> >> > Let's take an example.  There's plenty here:
> >> > https://en.cppreference.com/w/c/language/behavior.html
> >> > So let's focus on https://godbolt.org/z/48bn19Tsb
> >> >
> >> > For the lazy, I report it here:
> >> >
> >> >   int table[4] = {0};
> >> >   int exists_in_table(int v)
> >> >   {
> >> >       // return true in one of the first 4 iterations
> >> >       // or UB due to out-of-bounds access
> >> >       for (int i = 0; i <= 4; i++) {
> >> >           if (table[i] == v) return 1;
> >> >       }
> >> >       return 0;
> >> >   }
> >> >
> >> > This is compiled (with no warning whatsoever) into:
> >> >
> >> >   exists_in_table:
> >> >           mov     eax, 1
> >> >           ret
> >> >   table:
> >> >           .zero   16
> >> >
> >> >
> >> > Well, this is *obviously* wrong.  And sure, so is the original
> >> > code, but I find it hard to think that the compiler isn't able
> >> > to notice it, given that it is even "exploiting" it to produce
> >> > very efficient code.
> >> >
> >> > I understand the formalism:  the resulting assembly is formally
> >> > "correct", in that UB implies that anything can happen.
> >> > Yet I can't think of any situation where the resulting assembly
> >> > could be considered sensible.  The compiled function will
> >> > basically return 1 for any input, and the final program will be
> >> > buggy.
> >> >
> >> > Wouldn't it be more sensible to have a compilation error, or
> >> > at least a warning?  The compiler will be happy even with -Wall
> >> > -Wextra -Werror.
> >> >
> >> > There's plenty of documentation, articles and presentations that
> >> > explain how this can make very efficient code... but nothing
> >> > will answer this question:  do I really want to be efficiently
> >> > wrong?
> >> >
> >> > I mean, yes I would find the problem, thanks to my 100% coverage
> >> > unit testing, but couldn't the compiler give me a hint?
> >> >
> >> > Could someone drive me into this reasoning?  I know there is a
> >> > lot of thinking behind it, yet everything seems to me very
> >> > incorrect! I'm in deep cognitive dissonance here! :)  Help!    
> >> 
> >> The important thing to realize is that the fundamental issue here
> >> is not a technical question but a social question.  In effect what
> >> you are asking is "why doesn't gcc (or clang, or whatever) do what
> >> I want or expect?".  The answer is different people want or expect
> >> different things.  For some people the behavior described is
> >> egregiously wrong and must be corrected immediately.  For other
> >> people the compiler is acting just as they think it should,
> >> nothing to see here, just fix the code and move on to the next
> >> bug.  Different people have different priorities.
> >>  
> >
> > I have hard time imagining sort of people that would have
> > objections in case compiler generates the same code as today, but
> > issues diagnostic.  
> 
> If false positives occur for the diagnostic frequently, there
> will be legitimate complaint.
> 
> If there is only a simple switch for it, it will get turned off
> and then it no longer serves its purpose of catching errors.
> 
> There are all kinds of optimizations compilers commonly do that could
> also be erroneous situations. For instance, eliminating dead code.
> 
>   // code portable among several types of systems:
> 
>   switch (sizeof var) {
>   case 2: ...
>   case 4: ...
>   case 8: ...
>   }
> 
> sizeof var is a compile time constant expected to be 2, 4 or 8 bytes.
> The other cases are unreachable code.
> 
> Suppose every time the compiler eliminates unreachable code, it
> issues a diagnostic "foo.c:42: 3 lines of unreachable code removed".
> 
> That would be annoying when the programmer knows about dead code
> elimination and is counting on it.
> 
> We also have to consider that not all code is written directly by
> hand.
> 
> Code generation techniques (including macros) can produce "weird" code
> in some of their corner cases. The code is correct, and it would take
> more complexity to identify those cases and generate more idiomatic
> code; it is left to the compiler to clean up.
> 

[toc] | [prev] | [next] | [standalone]


#396333

FromMichael S <already5chosen@yahoo.com>
Date2026-01-10 18:41 +0200
Message-ID<20260110184106.0000431d@yahoo.com>
In reply to#396328
On Fri, 9 Jan 2026 20:14:04 -0000 (UTC)
Kaz Kylheku <046-301-5902@kylheku.com> wrote:

> On 2026-01-09, Michael S <already5chosen@yahoo.com> wrote:
> > On Fri, 09 Jan 2026 01:42:53 -0800
> > Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
> >  
> >> 
> >> The important thing to realize is that the fundamental issue here
> >> is not a technical question but a social question.  In effect what
> >> you are asking is "why doesn't gcc (or clang, or whatever) do what
> >> I want or expect?".  The answer is different people want or expect
> >> different things.  For some people the behavior described is
> >> egregiously wrong and must be corrected immediately.  For other
> >> people the compiler is acting just as they think it should,
> >> nothing to see here, just fix the code and move on to the next
> >> bug.  Different people have different priorities.
> >>  
> >
> > I have hard time imagining sort of people that would have
> > objections in case compiler generates the same code as today, but
> > issues diagnostic.  
> 
> If false positives occur for the diagnostic frequently, there
> will be legitimate complaint.
> 
> If there is only a simple switch for it, it will get turned off
> and then it no longer serves its purpose of catching errors.
> 
> There are all kinds of optimizations compilers commonly do that could
> also be erroneous situations. For instance, eliminating dead code.
> 

<snip>

I am not talking about  some general abstraction, but about specific
case.
You example is irrelevant.
-Warray-bounds exists for a long time. 
-Warray-bounds=1 is a part of -Wall set.
Message 'array subscript nnn is above array bounds' fits this
particular case as well as any other case when compiler does not forget
to issue it.
Defending gcc behavior of not issuing the enabled warning in situation
where compiler certainly detected out of bound access sounds like
Stockholm syndrome.










[toc] | [prev] | [next] | [standalone]


#396399

FromKaz Kylheku <046-301-5902@kylheku.com>
Date2026-01-13 23:31 +0000
Message-ID<20260113152223.17@kylheku.com>
In reply to#396333
On 2026-01-10, Michael S <already5chosen@yahoo.com> wrote:
> On Fri, 9 Jan 2026 20:14:04 -0000 (UTC)
> Kaz Kylheku <046-301-5902@kylheku.com> wrote:
>
>> On 2026-01-09, Michael S <already5chosen@yahoo.com> wrote:
>> > On Fri, 09 Jan 2026 01:42:53 -0800
>> > Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>> >  
>> >> 
>> >> The important thing to realize is that the fundamental issue here
>> >> is not a technical question but a social question.  In effect what
>> >> you are asking is "why doesn't gcc (or clang, or whatever) do what
>> >> I want or expect?".  The answer is different people want or expect
>> >> different things.  For some people the behavior described is
>> >> egregiously wrong and must be corrected immediately.  For other
>> >> people the compiler is acting just as they think it should,
>> >> nothing to see here, just fix the code and move on to the next
>> >> bug.  Different people have different priorities.
>> >>  
>> >
>> > I have hard time imagining sort of people that would have
>> > objections in case compiler generates the same code as today, but
>> > issues diagnostic.  
>> 
>> If false positives occur for the diagnostic frequently, there
>> will be legitimate complaint.
>> 
>> If there is only a simple switch for it, it will get turned off
>> and then it no longer serves its purpose of catching errors.
>> 
>> There are all kinds of optimizations compilers commonly do that could
>> also be erroneous situations. For instance, eliminating dead code.
>> 
>
><snip>
>
> I am not talking about  some general abstraction, but about specific
> case.
> You example is irrelevant.
> -Warray-bounds exists for a long time. 
> -Warray-bounds=1 is a part of -Wall set.

In your particular example, it is crystal clear that the "return 0"
statement is elided away due to being considered unreachable, and the
only reason for that can be undefined behavior, and the only undefined
behavior is accessing the array out of bounds.

The compiler has decided to use the undefined behavior of the OOB array
access as an unreachable() assertion, and at the same time neglected to
issue the -Warray-bounds diagnostic which is expected to be issued for
OOB access situations that the compiler can identify.

No one can claim that the OOB situation in the code has escaped
identification, because a code-eliminating optimization was predicated
on it.

It looks as if the logic for identifying OOB accesses for diagnosis is
out of sync with the logic for identifying OOB accesses as assertions of
undefined behavior.

In some situations, a surprising optimization occurs not because of
undefined behavior, but because the compiler is assuming well-defined
behavior (absence of UB).

That's not the case here; it is relying on the presence of UB. 

Or rather, it is relyiing on the absence of UB in an assinine way:
it is assuming that the program does not reach the out-of-bounds
access, because the sought-after value is found in the array.

But that reasoning requires awareness of the existence of the
out-of-bounds access.

That's the crux of the issue there.

There is an unreachable() assertion in modern C. And it works by
invoking undefined behavior; it means "let's have undefined behavior
in this spot of the code".  And then, since the compiler assumes
behavior is well-defined, assumes that that statement is not reached,
nor anything after it, and can eliminate it.

The problem is that an OOB array access should not be treated
as the same thing, as if it were unreachable(). Or, rather, no,
sure it's okay to treat an OOB arrary access as unreachable() --- IF
you generate the diagonstic about OOB array access that you
were asked to generate!!!

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca

[toc] | [prev] | [next] | [standalone]


Page 3 of 6 — ← Prev page 1 2 [3] 4 5 6  Next page →

Back to top | Article view | comp.lang.c


csiph-web