• Re: "RESET"

    From Don Y@21:1/5 to Don Y on Sat May 24 15:35:24 2025
    On 5/24/2025 3:34 PM, Don Y wrote:
    I don't quite understand the need for "reset" buttons on products.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene?  Particularly devices that are
    intended to "run forever"?

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    The same can be said of devices that need to be "restarted" (e.g.,
    for updates to be installed or "take effect")

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to All on Sat May 24 15:34:03 2025
    I don't quite understand the need for "reset" buttons on products.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene? Particularly devices that are
    intended to "run forever"?

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From john larkin@21:1/5 to [email protected] on Sat May 24 16:28:57 2025
    On Sat, 24 May 2025 15:34:03 -0700, Don Y
    <[email protected]d> wrote:

    I don't quite understand the need for "reset" buttons on products.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Power switches are not real any more. Mo's cable TV hangs up about
    once a month and the fix is to unplug it, wait a while, and plug it
    back in. Then it reloads its code from somewhere, for about 15
    minutes. So she misses the murder.


    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene? Particularly devices that are
    intended to "run forever"?

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    It is.

    We are living in the Dark Age of electronics. A bazillion hackers are
    designing a zillion cheap products, with basically no discipline.

    I wonder if things will ever get better. It would take a really good
    OS and some state-machine sort of language that really works. And a
    lot of serious reviewing and testing.

    And some legally-binding rules about user interfaces. In another
    hundrd years maybe.

    Hardware is better than software, mostly because it's more expensive
    to fix.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Carlos E. R.@21:1/5 to Don Y on Sun May 25 02:37:09 2025
    On 2025-05-25 00:34, Don Y wrote:
    I don't quite understand the need for "reset" buttons on products.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene?  Particularly devices that are
    intended to "run forever"?

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    Even the initial microprocessors have a reset pin. When they are powered
    up, the status of the electronics is unknown, so a small time after
    power up, the line is triggered by a timer (555 or whatever).

    Then, there are many designs where you can not pull power, because there
    is an unreachable battery.

    Then, it is impossible to guarantee that the device will never find
    itself in a pickle. No matter how fantastic the designers are.

    --
    Cheers,
    Carlos E.R.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Carlos E. R. on Sat May 24 19:01:14 2025
    On 5/24/2025 5:37 PM, Carlos E. R. wrote:
    Even the initial microprocessors have a reset pin. When they are powered up, the status of the electronics is unknown, so a small time after power up, the line is triggered by a timer (555 or whatever).

    Usually, reset is asserted as power is being applied (PoR). One can
    also design silicon with internal reset generators (though these often
    rely on particular power application characteristics)

    But, thereafter, there should be no need to be able to FORCE a reset
    condition beyond that which occurs as part of PoR.

    It certainly shouldn't be needed to recover from an errant processor.

    Then, there are many designs where you can not pull power, because there is an
    unreachable battery.

    So, the battery is inaccessible but a reset button wouldn't be?
    All the more reason NOT to need a reset button!

    Then, it is impossible to guarantee that the device will never find itself in a
    pickle. No matter how fantastic the designers are.

    Barring hardware failures, software should be able to sort itself out,
    even if it means resorting to panic() -- which can be the equivalent of
    the startup code being re-executed.

    For device in question (a PLC modem) likely relies on reset for
    hardware design deficiencies as the software itself is pretty trivial.

    It would be amusing to apply odd "DC" power to various devices and watch
    how they misbehave ("Well, that's not what we expected when we specified
    X volts @ Y amps" "Oh, well asking to examine drive 7 isn't what
    was expected when we designed this TWO drive machine! Yet, if you try
    to do so, you expect the software to 'behave' despite your ignorance
    if what was expected?")

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralph Mowery@21:1/5 to All on Sat May 24 23:47:08 2025
    In article <100thgs$v8cm$[email protected]>, [email protected]d
    says...

    I don't quite understand the need for "reset" buttons on products.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene? Particularly devices that are
    intended to "run forever"?

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...


    Sometimes it is the user that is lacking. Such as forgetting a
    password. Maybe putting the device in the wrong mode and can not
    remember how to get it out of that mode.

    With the many lines of code it is impossiable to check out every
    possiale combination of things that could ge wrong in a reasonable time.

    While not really much of a chance but in the eairly days bits could be randomally changed by stray radiation.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Ralph Mowery on Sat May 24 22:58:45 2025
    On 5/24/2025 8:47 PM, Ralph Mowery wrote:
    Sometimes it is the user that is lacking. Such as forgetting a
    password. Maybe putting the device in the wrong mode and can not
    remember how to get it out of that mode.

    And cycling power won't suffice?

    With the many lines of code it is impossiable to check out every
    possiale combination of things that could ge wrong in a reasonable time.

    You let the code catch the mistakes. Any time two pieces of
    code ("modules") interact, a formal interface SHOULD exist that
    defines the contract that both parties will observe. Instead
    of just HOPING that the other guy is holding up his end of
    the contract, write code to CATCH those times when he clearly isn't.

    When you find such an instance, "something is wrong"; either an
    assumption made at design time, a bug in an implementation, or
    a hardware fault that has corrupted data or execution (any product
    that uses memory is subject to all sorts of faults; the more memory
    and higher frequency of access then the greater the *likelihood*
    of errors).

    A staple of robust software development practices is formalizing
    these interfaces and adding invariants to enforce them at run time
    (these things almost never have a significant impact on performance
    if implemented properly).

    You know to check before dividing a value into another (divide by
    zero). Have you asked yourself WHY the possibility of "zero"
    exists in your code? Or, "negative time"? Have you modeled
    the problem correctly?

    While not really much of a chance but in the eairly days bits could be randomally changed by stray radiation.

    Errors can be induced from the "traffic" within a device
    (read and write disturb) without having to worry about radiation.
    (thought there have been some studies that show a positive correlation
    of error rates with elevation)

    Hardware isn't as reliable as folks would like to think.
    So, you have to design algorithms and styles that catch
    the hardware when it is misbehaving (otherwise, you will
    naively blame it on a software "bug" -- because you
    don't understand how the hardware is failing nor have
    tools to MEASURE those failures)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ian@21:1/5 to Don Y on Sun May 25 08:01:58 2025
    On 2025-05-24, Don Y <[email protected]d> wrote:
    I don't quite understand the need for "reset" buttons on products.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene? Particularly devices that are
    intended to "run forever"?

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    Ususally the "reset" button is really "factory reset", which is intended
    to revert persistent state back to know values. A typical use for this,
    that absolutely must not be done on a power cycle, is setting a login
    password to a known value ("1234", or some more secure unique string
    printed on a label if the designer is sensible).

    As a convenience (for who?), a quick press of the reset button usually
    just does a POR, and you need to hold the button for some length of time
    to reset the configuration. I think this has just become a convention
    that every device seems to follow.

    Yes, a lot of complex devices that really should be able to run forever sometimes can't, and lock up. I blame lack of understanding of the whole
    system by the programmers (and it is usually software that is at fault,
    rarely the hardware). It's going to get worse with completely clueless
    people throwing together something that barely works with the help of
    automated idiots.

    I write microcontroller code in assembler that runs 24x7x365x∞ (that's "infinity", for the UTF8-challenged :)

    --
    Ian

    "Tamahome!!!" - "Miaka!!!"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Theo@21:1/5 to Don Y on Sun May 25 10:07:11 2025
    Don Y <[email protected]d> wrote:
    I don't quite understand the need for "reset" buttons on products.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene? Particularly devices that are
    intended to "run forever"?

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    Nowadays 'reset' often means 'reset to factory settings' rather than
    'reboot'. The factory settings reset is needed because maybe you forgot the password and have no other way to reconfigure the thing. Or you need to
    make it go back into the initial pairing mode so you can attach it to
    another network/etc.

    Having a physical factory reset button means that somebody with physical
    access can always regain access to it. You can also use it to verify destructive actions (eg 'to wipe all the data, now hold the button') so that they can't be done remotely.

    In practical terms such a button might just be a GPIO rather than wired to a reset line, and the software pays attention to it at certain times such as during boot.

    For more developer-focused devices, a true reset button is also better than yanking the power cord which can cause wear on the connectors. So when
    version 497 of your code crashes you can hit the button and upload v498.

    Theo

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Martin Brown@21:1/5 to Don Y on Sun May 25 10:19:41 2025
    On 24/05/2025 23:34, Don Y wrote:
    I don't quite understand the need for "reset" buttons on products.

    There are things like routers and mobile phones where there is a very significant difference between power on/off and a hard factory reset.
    The former recovers it form having crashed internally whilst the latter
    trashes all previous settings into oblivion.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Not always available - there are quite a few different levels of reset
    too. I recall one particularly annoying one on an early Android device
    that require holding the on/off button and volume down in for 4 minutes.
    It did do a hard factory reset on about the fifth attempt. The previous
    four having failed because my fingers slipped. One minor annoyance was
    that the very hard reset put it into Chinese language mode.

    ISTR the ordinary soft factory reset was about 10s holding the magic
    buttons in (but didn't work on this unit).

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene?  Particularly devices that are
    intended to "run forever"?

    In an ideal world yes. But I have seen such devices in a state where the
    only process still running was the one pressing the dead man's handle to
    say that everything is OK. Many routers tend to go haywire after a
    continuous uptime of about 2 or 3 months having fragmented their stack.

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    It could also be to reset to a known state. Several of the more annoying gadgets have one time programmability from a PC but to make them secure
    the moment you make them active all further communication is impossible.

    The only way to reprogram is factory reset and start again from scratch.
    User interface designed by someone who really enjoyed the maze in Zork.
    (some TV tuning menus fall into this category)

    --
    Martin Brown

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Theo on Sun May 25 02:59:17 2025
    On 5/25/2025 2:07 AM, Theo wrote:
    Don Y <[email protected]d> wrote:
    I don't quite understand the need for "reset" buttons on products.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene? Particularly devices that are
    intended to "run forever"?

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    Nowadays 'reset' often means 'reset to factory settings' rather than 'reboot'. The factory settings reset is needed because maybe you forgot the password and have no other way to reconfigure the thing. Or you need to
    make it go back into the initial pairing mode so you can attach it to
    another network/etc.

    As I said elsewhere, that's different than something that actually RESETS
    the processor. You could just as easily have a BUTTON labeled "restore
    factory defaults" and a protocol as to when it is recognized, when it
    takes effect, etc.

    The "reset" that I am talking about tugs on the reset pin of the processor(s) and ensures it/they return to a known state comparable to initial power up.
    It doesn't rely on the software "cooperating" in order to take effect.

    Having a physical factory reset button means that somebody with physical access can always regain access to it. You can also use it to verify destructive actions (eg 'to wipe all the data, now hold the button') so that they can't be done remotely.

    But, again, that can be labeled as such and INTERPRETED by the software;
    not ENFORCED by the hardware.

    In practical terms such a button might just be a GPIO rather than wired to a reset line, and the software pays attention to it at certain times such as during boot.

    Yes. Or, at any other point in the UX.

    For more developer-focused devices, a true reset button is also better than yanking the power cord which can cause wear on the connectors. So when version 497 of your code crashes you can hit the button and upload v498.

    But, you can do that by tacking something across the reset/ground lines.
    No need to bear a recurring cost for it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Ian on Sun May 25 02:53:04 2025
    On 5/25/2025 1:01 AM, Ian wrote:
    Ususally the "reset" button is really "factory reset", which is intended
    to revert persistent state back to know values. A typical use for this,
    that absolutely must not be done on a power cycle, is setting a login password to a known value ("1234", or some more secure unique string
    printed on a label if the designer is sensible).

    That's a user-interface function. Just like any other key/button.
    Pressing it ONLY works when the product is behaving properly-enough
    to understand that UI aspect. A "crashed" program would likely
    not see that as the event intended.

    I'm talking about something that literally resets the processor.

    As a convenience (for who?), a quick press of the reset button usually
    just does a POR, and you need to hold the button for some length of time
    to reset the configuration. I think this has just become a convention
    that every device seems to follow.

    But, that still resets the processor. Encoding the desire to "reset to
    factory defaults" in the time domain (i.e., examine the button N seconds
    after RESET to determine if you should ALSO reset the defaults) relies
    on having first RESET the CPU.

    Resetting defaults can happen without the need for a CPU reset.

    Yes, a lot of complex devices that really should be able to run forever sometimes can't, and lock up. I blame lack of understanding of the whole system by the programmers (and it is usually software that is at fault, rarely the hardware). It's going to get worse with completely clueless
    people throwing together something that barely works with the help of automated idiots.

    I see more and more cases of hardware that isn't up to the task.
    No mechanisms for reporting memory errors to the software, spurious
    interrupts, glitchy power supplies, etc.

    As software gets more complex -- and people naively embrace "undocumented SOFTWARE components" ("What's this big chip that takes up most of the design? Do we have a detailed datasheet for it?") for which they have scant
    concrete data and little first hand expertise -- there are more opportunities for "gee, I didn't realize that could happen!"

    I write microcontroller code in assembler that runs 24x7x365x∞ (that's "infinity", for the UTF8-challenged :)

    I stopped writing in ASM when my projects got to 250KB binaries.
    It's just too hard for others to follow along at that level of
    complexity.

    But, it's relatively easy to write code that WILL run 24/7/365 -- if
    the hardware cooperates. Sad as hardware is so easy/inexpensive to change
    yet the burden always falls on the software. (look at the DM+DL of a
    product. how many developer hours would that pay for? multiply by the
    number of units sold. Wouldn't it be cheaper to just replace the hardware
    than pay someone man-months to change the software??)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Martin Brown on Sun May 25 03:15:12 2025
    On 5/25/2025 2:19 AM, Martin Brown wrote:
    On 24/05/2025 23:34, Don Y wrote:
    I don't quite understand the need for "reset" buttons on products.

    There are things like routers and mobile phones where there is a very significant difference between power on/off and a hard factory reset. The former recovers it form having crashed internally whilst the latter trashes all
    previous settings into oblivion.

    Yes, but (as stated elsewhere), that is part of the UI. Software *interprets* it. And, can ignore it if the device model says it SHOULD ignore it at
    this point in time.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Not always available - there are quite a few different levels of reset too. I recall one particularly annoying one on an early Android device that require holding the on/off button and volume down in for 4 minutes. It did do a hard factory reset on about the fifth attempt. The previous four having failed because my fingers slipped. One minor annoyance was that the very hard reset put it into Chinese language mode.

    ISTR the ordinary soft factory reset was about 10s holding the magic buttons in
    (but didn't work on this unit).

    But those are user interface functions.

    PCs have *hardware* that implements the "4 second power off" (regardless of state of CPU). It's part of the SuperIO. I.e., a *real* RESET that doesn't require the cooperation of the CPU. An acknowledgement that the CPU can go south and not recover.

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene?  Particularly devices that are
    intended to "run forever"?

    In an ideal world yes. But I have seen such devices in a state where the only process still running was the one pressing the dead man's handle to say that everything is OK. Many routers tend to go haywire after a continuous uptime of
    about 2 or 3 months having fragmented their stack.

    That's a poor design. The thing that strokes the watchdog mechanism
    should, itself, be reliant on proper operation of the rest of the device.
    I've seen designs where a timer started a process that stroked the
    watchdog and then slept awaiting the next timer invocation. Clearly
    not doing what it was intended to do as damn near everything in the machine
    can be hosed and that process still functioning properly.

    The epitome of this is "let's set up an interrupt that will stroke
    the watchdog FOR us! That way, we won't have to worry about being
    too busy to get around to doing it in a timely manner!"

    Such interfaces shouldn't be purely "time" based. I always use a second
    (dirt cheap, small package) MCU to act as a reset controller. It "talks"
    with an application in the main processor so *it* can exercise some
    judgement as to whether or not the main processor is "sane". It can
    also hinder counterfeiting as one can usually get a small, "secure" MCU
    whereas trying to "secure" a larger device becomes difficult (e.g., the
    memory and busses can easily be monitored)

    It controls the RESET signal as well as the RESETIO signals so *it* can
    bring the field to a safe state even if the main processor is completely
    hosed.

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    It could also be to reset to a known state. Several of the more annoying gadgets have one time programmability from a PC but to make them secure the moment you make them active all further communication is impossible.

    That's often to discourage hacking.

    The only way to reprogram is factory reset and start again from scratch. User interface designed by someone who really enjoyed the maze in Zork.
    (some TV tuning menus fall into this category)


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Carlos E. R.@21:1/5 to Don Y on Sun May 25 21:18:13 2025
    On 2025-05-25 04:01, Don Y wrote:
    On 5/24/2025 5:37 PM, Carlos E. R. wrote:

    ...

    Then, there are many designs where you can not pull power, because
    there is an unreachable battery.

    So, the battery is inaccessible but a reset button wouldn't be?
    All the more reason NOT to need a reset button!

    Think phones.


    Then, it is impossible to guarantee that the device will never find
    itself in a pickle. No matter how fantastic the designers are.

    Barring hardware failures, software should be able to sort itself out,

    Should.

    Actually, nobody warranties this. Oh, wait, I remember a company that
    did warranty it, for limited sized code, and hugely expensive. They did
    the core software on ATMs or the servers behind them, I don't remember.

    ...

    --
    Cheers,
    Carlos E.R.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Joe Gwinn@21:1/5 to [email protected] on Sun May 25 15:33:43 2025
    On Sun, 25 May 2025 02:37:09 +0200, "Carlos E. R."
    <[email protected]d> wrote:

    On 2025-05-25 00:34, Don Y wrote:
    I don't quite understand the need for "reset" buttons on products.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene?� Particularly devices that are
    intended to "run forever"?

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    Even the initial microprocessors have a reset pin. When they are powered
    up, the status of the electronics is unknown, so a small time after
    power up, the line is triggered by a timer (555 or whatever).

    Then, there are many designs where you can not pull power, because there
    is an unreachable battery.

    Then, it is impossible to guarantee that the device will never find
    itself in a pickle. No matter how fantastic the designers are.

    Exactly. I recall a customer wanting us to verify all possible paths
    through a bit of air traffic control radar software, about 100,000
    lines of plain C. Roughly one in five executable line was an IF
    statement, which is 20,000 IF statements. So there are 2^20000 =
    10^6020 such paths.

    The testing campaign will have only scratched the surface when the Sun
    runs out of hydrogen and goes supernova. Tomorrow's problem.

    Joe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Carlos E. R.@21:1/5 to Ralph Mowery on Sun May 25 21:20:40 2025
    On 2025-05-25 05:47, Ralph Mowery wrote:
    While not really much of a chance but in the eairly days bits could be randomally changed by stray radiation.

    And today. It is even a bigger chance, with lower logic voltages. Chips
    are not shielded.

    --
    Cheers,
    Carlos E.R.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Carlos E. R.@21:1/5 to Don Y on Sun May 25 21:22:04 2025
    On 2025-05-25 07:58, Don Y wrote:
    And cycling power won't suffice?

    Some designs preserve the status on power cycle. Intentionally.

    --
    Cheers,
    Carlos E.R.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Carlos E. R.@21:1/5 to Martin Brown on Sun May 25 21:31:35 2025
    On 2025-05-25 11:19, Martin Brown wrote:

    ...


    Not always available - there are quite a few different levels of reset
    too. I recall one particularly annoying one on an early Android device
    that require holding the on/off button and volume down in for 4 minutes.
    It did do a hard factory reset on about the fifth attempt. The previous
    four having failed because my fingers slipped. One minor annoyance was
    that the very hard reset put it into Chinese language mode.

    Wow! :-o

    --
    Cheers,
    Carlos E.R.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Carlos E. R. on Sun May 25 13:23:50 2025
    On 5/25/2025 12:22 PM, Carlos E. R. wrote:
    On 2025-05-25 07:58, Don Y wrote:
    And cycling power won't suffice?

    Some designs preserve the status on power cycle. Intentionally.

    Then they have obviously added a user interface capability elsewhere
    to "reset settings". Otherwise, a crashed CPU can just as easily
    crash when "reset" as the environment is unchanged and likely to repeat.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Carlos E. R. on Sun May 25 13:35:26 2025
    On 5/25/2025 12:20 PM, Carlos E. R. wrote:
    On 2025-05-25 05:47, Ralph Mowery wrote:
    While not really much of a chance but in the eairly days bits could be
    randomally changed by stray radiation.

    And today. It is even a bigger chance, with lower logic voltages. Chips are not
    shielded.

    Depending on the technology, just accessing a memory cell can degrade it's content. When you are storing a handful of electrons, any couple that
    manage to "leak out" can alter the perceived state of that cell.

    Accesses to "nearby" cells/wordlines, etc.

    Expecting memory to "remember" is naive, nowadays.

    For devices that load RAM from a (slower) FLASH store, there is no
    guarantee that the contents of the RAM mirror the FLASH any time later.
    Even assuming errant software doesn't "accidentally" corrupt it.

    Do you *routinely* verify it's integrity? How often? What do
    you do WHEN you discover a bit has been corrupted in the TEXT?

    How confident does that make you about the DATA??

    "Oh, the hardware is reliable" Then, you should be able to PROVE
    this assertion. Monitor EVERY access (in a test fixture) and
    verify they agree with a duplicate store maintained "outside"
    the product.

    Or, just look at the research others have done and realize your reliability assumptions are likely wishful thinking. ("Ah, but we can blame the
    software for any anomalous behavior!" And, NEVER manage to find "the bug"
    or FIX it!)

    In the days of toy products (a few kiloBITS of RAM made with very
    large geometries and slow cycle times), you could reasonably hope
    for a long time between failures. (And, failures need not manifest
    as changes from desired behavior! "4 >> 1" yields the same result
    as "5 >> 1". "JMP if ODD" yields the same behavior as "JMP unconditionally"
    if the test just *happens* to be ODD)

    Nowadays, its so easy to have megabytes and gigabytes of RAM in
    a device and few XIP like days of old. So, the risks causes double.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Carlos E. R. on Sun May 25 13:22:09 2025
    On 5/25/2025 12:18 PM, Carlos E. R. wrote:
    On 2025-05-25 04:01, Don Y wrote:
    On 5/24/2025 5:37 PM, Carlos E. R. wrote:

    ...

    Then, there are many designs where you can not pull power, because there is >>> an unreachable battery.

    So, the battery is inaccessible but a reset button wouldn't be?
    All the more reason NOT to need a reset button!

    Think phones.

    Does "reset" actually reset the phone's CPU? Or, just reset the *settings*
    in the phone? That's the difference I'm trying to highlight. Reseting *settings* is just a UI capability.

    Then, it is impossible to guarantee that the device will never find itself >>> in a pickle. No matter how fantastic the designers are.

    Barring hardware failures, software should be able to sort itself out,

    Should.

    Actually, nobody warranties this. Oh, wait, I remember a company that did warranty it, for limited sized code, and hugely expensive. They did the core software on ATMs or the servers behind them, I don't remember.

    There are lots of industries that expect devices to perform as specified.
    (The trick is finding competent people to write and review the specifications).

    You don't need to test every combination ox X and Y to verify multiply(X,Y)
    is implemented correctly; that would be a foolish approach to the problem.

    You craft software so you can identify the "corner cases" of interest to
    a particular algorithm/implementation and test THOSE. Then, expect everything "in the middle" to behave. I.e., why *should* mul(3,Y) be any different
    than mul(5,Y) -- in the GENERAL case?

    [This is where you engineer your algorithm and test cases accordingly. E.g., if I perform mul(3,Y) as add(Y, 2Y) then it would likely require separate testing from mul(5,Y) as add(Y, 4Y). But, otherwise, the only interesting cases are mul(0,Y), mul(X,0), mul(X,-Y), mul(-X,Y) and variations on "big" arguments (i.e., to verify overflow is handled appropriately: which would differ based on how overflow is SUPPOSED to be handled -- saturated
    arithmetic, etc.)]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Joe Gwinn on Tue May 27 14:13:02 2025
    On 5/25/2025 12:33 PM, Joe Gwinn wrote:
    Exactly. I recall a customer wanting us to verify all possible paths
    through a bit of air traffic control radar software, about 100,000
    lines of plain C. Roughly one in five executable line was an IF
    statement, which is 20,000 IF statements. So there are 2^20000 =
    10^6020 such paths.

    And probably 99.9% of them are superfluous.

    if (x % 2) {
    x++
    }

    if (y == green) {
    // do something
    }

    if (z < 0) {
    // something else
    }

    The first conditional just deals with making "odd" values of x into even ones. That can be completely tested regardless of which -- if any -- of the following or preceding conditionals are invoked. I.e., you don't need to test for
    x even, y green
    x odd, y green
    x even, y notgreen
    x odd, y notgreen
    Rather, you verify the correct operation of the first conditional with
    a range of even and odd values (more than two are required to address
    the proper operation with negative numbers, "zero" and any other special cases that your compiler might tickle.

    Then, with x now guaranteed to be even, you can try y as green and notgreen.

    Then, with z positive vs non-negative.

    I.e., approximately two cases for each conditional so 3*2=6 cases instead
    of geometric explosion (2^3=8)

    Experience teaches you to construct your code so that testability is
    enhanced. Instead of waiting until it seems to be "done" and then
    trying to reassure yourself that it works as intended -- usually by
    throwing EXPECTED conditions at it and hoping for the expected
    results (that's not testing).

    You need 2^20000 if there are 2^20000 distinct outcomes (leaf nodes) in
    your code. I strongly doubt that to be the case.

    The testing campaign will have only scratched the surface when the Sun
    runs out of hydrogen and goes supernova. Tomorrow's problem.

    How do you test an electronic circuit? Let's impose an infinite number of discrete voltages on each of the input signals and verify the correct
    outputs for each? (Do you deliberately verify all ranges of signal values
    and frequencies? Or, just say "operation outside of these conditions is indeterminate"?)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Joe Gwinn@21:1/5 to [email protected] on Tue May 27 19:13:28 2025
    On Tue, 27 May 2025 14:13:02 -0700, Don Y
    <[email protected]d> wrote:

    On 5/25/2025 12:33 PM, Joe Gwinn wrote:
    Exactly. I recall a customer wanting us to verify all possible paths
    through a bit of air traffic control radar software, about 100,000
    lines of plain C. Roughly one in five executable line was an IF
    statement, which is 20,000 IF statements. So there are 2^20000 =
    10^6020 such paths.

    And probably 99.9% of them are superfluous.

    [snip]

    The problem is that you have no way to know which cases are
    irrelevant. And practical hardware will have many things able to
    retain state.


    Experience teaches you to construct your code so that testability is >enhanced. Instead of waiting until it seems to be "done" and then
    trying to reassure yourself that it works as intended -- usually by
    throwing EXPECTED conditions at it and hoping for the expected
    results (that's not testing).

    It is not usually the expected that causes trouble: It ain't what you
    don't know that matters, it what you know that ain't so that's the
    problem.


    You need 2^20000 if there are 2^20000 distinct outcomes (leaf nodes) in
    your code. I strongly doubt that to be the case.

    So assume only 1000 IF statements, so it's 2^1000 or 10^600 or so.
    You'll still run out of lifetime.


    The testing campaign will have only scratched the surface when the Sun
    runs out of hydrogen and goes supernova. Tomorrow's problem.

    How do you test an electronic circuit? Let's impose an infinite number of >discrete voltages on each of the input signals and verify the correct
    outputs for each? (Do you deliberately verify all ranges of signal values >and frequencies? Or, just say "operation outside of these conditions is >indeterminate"?)

    You do all the tests for required behavior - does it meet stated
    requirements.

    Then you random probe it for weeks and see what goes Bang!

    One form of this is Fuzzing.

    .<https://www.usenix.org/conference/usenixsecurity22/presentation/trippel>

    Joe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Joe Gwinn on Tue May 27 17:40:44 2025
    On 5/27/2025 4:13 PM, Joe Gwinn wrote:
    On Tue, 27 May 2025 14:13:02 -0700, Don Y
    <[email protected]d> wrote:

    On 5/25/2025 12:33 PM, Joe Gwinn wrote:
    Exactly. I recall a customer wanting us to verify all possible paths
    through a bit of air traffic control radar software, about 100,000
    lines of plain C. Roughly one in five executable line was an IF
    statement, which is 20,000 IF statements. So there are 2^20000 =
    10^6020 such paths.

    And probably 99.9% of them are superfluous.

    [snip]

    The problem is that you have no way to know which cases are
    irrelevant. And practical hardware will have many things able to
    retain state.

    The design of the specification becomes important.
    The *implementor* can further refine the test cases based
    on other potential vulnerabilities that his implementation
    may create.

    E.g., if you implement a multiply routine with repeated
    additions of the multiplicand, the case where the multiplier
    is zero can be buggy -- because you may have examined
    the "remaining multiplier" in a place that assumes at
    least one iteration of the multiplicand's processing.

    Or, a negative multiplier (how do you run a loop some
    negative number of times?)

    Experience teaches you to construct your code so that testability is
    enhanced. Instead of waiting until it seems to be "done" and then
    trying to reassure yourself that it works as intended -- usually by
    throwing EXPECTED conditions at it and hoping for the expected
    results (that's not testing).

    It is not usually the expected that causes trouble: It ain't what you
    don't know that matters, it what you know that ain't so that's the
    problem.

    Which is why it is so easy to prove code doesn't work! You
    identify what the likely assumptions were and then challenge
    each of those. People treat assumptions as so ingrained
    that they never actually consider their validity: Will
    this value always be non-zero? will the datalogger
    always be powered on? will "spare" memory always be
    available?

    Attack one and watch the code flail about -- because it's
    expectations have been defied.

    You need 2^20000 if there are 2^20000 distinct outcomes (leaf nodes) in
    your code. I strongly doubt that to be the case.

    So assume only 1000 IF statements, so it's 2^1000 or 10^600 or so.
    You'll still run out of lifetime.

    If you have 1000 if statements in a module, then your module is
    at least 16 pages long -- containing no OTHER code. This is why
    you make small modules so their complete behavior can be "groked"
    without having ludicrous levels of complexity.

    if (x==0) {
    //
    } else if (x==1) {
    //
    } else if (x==2) {
    //
    } else if (x==3) {
    //
    } else {
    //
    }

    Four conditionals. 6 test cases for 100% coverage (<0, 0, 1, 2, 3, >=4)
    Not 16.

    I.e., assuming complexity correlates with a geometric weighing of
    the number of conditionals is specious reasoning.

    The testing campaign will have only scratched the surface when the Sun
    runs out of hydrogen and goes supernova. Tomorrow's problem.

    How do you test an electronic circuit? Let's impose an infinite number of >> discrete voltages on each of the input signals and verify the correct
    outputs for each? (Do you deliberately verify all ranges of signal values >> and frequencies? Or, just say "operation outside of these conditions is
    indeterminate"?)

    You do all the tests for required behavior - does it meet stated requirements.

    But, you only test the *boundary* conditions. I.e., if something is
    suposed to work over a range of 0 - 12 volts, you test 0, 12, something
    in between and then < 0 and > 12. You don't test 0, 0.1, 0.2, 0.3, 0.4,
    0.5, 0.50000000000001, 0.5000000000002, etc.

    Because you know the circuit is well-behaved BETWEEN these conditions.

    A UNIX pathname can be thousands of characters long. Do you test:
    a
    b
    c
    d
    ...
    z
    A
    ...
    Z
    0
    ...
    9
    aa
    ab
    ...
    az
    ...
    Of course not! Yet, a test case like:
    /0/1/2/3/4/../../../../../../../../../../../../../../../..
    could tickle a bug in the implementation.

    UNLESS, the implementor took a shortcut that exposed some buried
    condition that needs to be exposed to testing. E.g., if he
    routed the signal through two different paths based on whether
    or not it exceeded 5 volts.

    The specification likely won't have anticipated such an "optimization"
    so wouldn't have drawn attention to "5V" as a particularly important case.
    The implementor/designer has to understand how his implementation could potentially break in ways that the specification couldn't catch.

    Then you random probe it for weeks and see what goes Bang!

    One form of this is Fuzzing.

    .<https://www.usenix.org/conference/usenixsecurity22/presentation/trippel>

    You still rely on "luck" to stumble on bugs. You need good specifications, "bite size" modules (where complexity is limited) and implementors who
    are aware of testing IN their design choices -- so they don't meet
    the published specifications (and likely test cases) but still fail,
    miserably when their internal quirks are tickled.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Martin Brown@21:1/5 to Joe Gwinn on Wed May 28 09:43:00 2025
    On 25/05/2025 20:33, Joe Gwinn wrote:
    On Sun, 25 May 2025 02:37:09 +0200, "Carlos E. R."
    <[email protected]d> wrote:

    On 2025-05-25 00:34, Don Y wrote:
    I don't quite understand the need for "reset" buttons on products.

    That function is always available by cycling power -- even for devices
    where that is difficult for the user (e.g., PoE, BBU, etc.)

    Shouldn't a device be able to get itself out of a "pickle" without
    requiring the user to intervene?  Particularly devices that are
    intended to "run forever"?

    I.e., it seems like the presence of a reset button is a tacit admission
    that the engineering is "lacking"...

    Even the initial microprocessors have a reset pin. When they are powered
    up, the status of the electronics is unknown, so a small time after
    power up, the line is triggered by a timer (555 or whatever).

    Then, there are many designs where you can not pull power, because there
    is an unreachable battery.

    Then, it is impossible to guarantee that the device will never find
    itself in a pickle. No matter how fantastic the designers are.

    Exactly. I recall a customer wanting us to verify all possible paths
    through a bit of air traffic control radar software, about 100,000
    lines of plain C. Roughly one in five executable line was an IF
    statement, which is 20,000 IF statements. So there are 2^20000 =
    10^6020 such paths.

    Executing each path in the code at least once is a much more tractable
    problem. McCabes CCI metric will tell you how many test vectors it will
    take for a given complexity of code. And it should be done.

    A sufficiently high CCI index for a routine also means that such code is
    highly unlikely to be correct.

    I recall one instance on a mainframe (brand withheld to protect the
    guilty) where a rogue program that ran continuously was slowly using up
    IO handles repeatedly opening the tracker ball interface each time a new
    user accessed it (and never letting go).

    One day after a particularly long uptime it completely ran out of IO
    handles. Guess what the first thing the error handler tried to do?

    Yup! It tried to obtain a new IO handle to report the error!

    The testing campaign will have only scratched the surface when the Sun
    runs out of hydrogen and goes supernova. Tomorrow's problem.

    You can't out test every possible combination of events but you can make
    sure that the code paths when executed in at least one scenario don't do anything horribly bad. A lot of faults can lurk in the rarely used error recovery code that only gets used after something else has gone wrong.

    Ariane 5 was an example of that sort of thing.
    comp.risks is littered with them.

    --
    Martin Brown

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Martin Brown on Wed May 28 03:23:10 2025
    On 5/28/2025 1:43 AM, Martin Brown wrote:
    Exactly.  I recall a customer wanting us to verify all possible paths
    through a bit of air traffic control radar software, about 100,000
    lines of plain C.  Roughly one in five executable line was an IF
    statement, which is 20,000 IF statements.  So there are 2^20000 =
    10^6020 such paths.

    Executing each path in the code at least once is a much more tractable problem.
    McCabes CCI metric will tell you how many test vectors it will take for  a given complexity of code. And it should be done.

    But you don't need to execute each *combination* of paths. All you
    have to do is test the code in each branch (and opposing instance).

    A sufficiently high CCI index for a routine also means that such code is highly
    unlikely to be correct.

    Yes. You want modules to be small and self-contained. This is the appeal
    of OOPS. Procedural implementations tend to meander around the codebase,
    as if they are remembering particular issues as they wander. Instead,
    focusing on a single, well-defined operation -- on a single object -- gives
    you a simpler piece of code that is easier to comprehesively test

    I recall one instance on a mainframe (brand withheld to protect the guilty) where a rogue program that ran continuously was slowly using up IO handles repeatedly opening the tracker ball interface each time a new user accessed it
    (and never letting go).

    One day after a particularly long uptime it completely ran out of IO handles. Guess what the first thing the error handler tried to do?

    Yup! It tried to obtain a new IO handle to report the error!

    Of course! The fault, there, was not taking the handle early on, to be sure
    it would be available. E.g., the difference between allocating dynamic resources AS IF static -- just to avoid the possibility of them not being available when needed. Ooops!

    The testing campaign will have only scratched the surface when the Sun
    runs out of hydrogen and goes supernova.  Tomorrow's problem.

    You can't out test every possible combination of events but you can make sure that the code paths when executed in at least one scenario don't do anything horribly bad. A lot of faults can lurk in the rarely used error recovery code that only gets used after something else has gone wrong.

    Ariane 5 was an example of that sort of thing.

    Proof that big, well-funded projects doesn't correlate with BETTER implementations! When a project gets too big, group think muddies
    the details of importance.

    comp.risks is littered with them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Joe Gwinn on Wed May 28 14:41:56 2025
    On 28/05/2025 01:13, Joe Gwinn wrote:
    On Tue, 27 May 2025 14:13:02 -0700, Don Y
    <[email protected]d> wrote:

    On 5/25/2025 12:33 PM, Joe Gwinn wrote:
    Exactly. I recall a customer wanting us to verify all possible paths
    through a bit of air traffic control radar software, about 100,000
    lines of plain C. Roughly one in five executable line was an IF
    statement, which is 20,000 IF statements. So there are 2^20000 =
    10^6020 such paths.

    And probably 99.9% of them are superfluous.

    [snip]

    The problem is that you have no way to know which cases are
    irrelevant. And practical hardware will have many things able to
    retain state.


    A concept you are looking for here is "cyclomatic complexity" :

    <https://en.wikipedia.org/wiki/Cyclomatic_complexity>

    Conditionals are not independent (in most cases) - thus the number of
    paths through code is not simply two to the power of the number of if statements.

    (McCabe cyclomatic complexity measures are not the only way to look at
    this, and like anything else, the measure has its advantages and
    disadvantages, and is not suitable for everything. But it's a
    reasonable place to start.)

    The way you handle complexity in software is exactly the same as any
    other complexity - you break things down into manageable parts. For
    software, that can be libraries, modules, files, classes, functions, and blocks. You specify things from the top down, and test them from the
    bottom up. How much testing you do, and how you do it, is going to
    depend on the application - an air traffic control system will need more thorough testing than a mobile phone game.

    When you are looking at a function, the cyclomatic complexity can be
    calculated by tools. It will then give you a good idea of how much
    testing you need for the function. Too high a complexity, and you will
    never be able to test the function to get a solid idea of its
    correctness, as you would need too many test cases for practicality.
    (You may still be able to use other analysis methods.) The complexity
    can also give a good indication of how easy it is for humans to
    understand the function and judge its correctness. (Again, no one
    measure gives a complete picture.)

    Other tools that can be useful in testing are code coverage tools - you
    can check that your test setups check all paths through the code.


    But remember that testing cannot prove the absence of bugs - only their presence. And it only works on the assumption that the hardware is
    correct - even when the software is perfect, you might still need that
    reset button or a watchdog!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Joe Gwinn@21:1/5 to [email protected] on Wed May 28 12:07:01 2025
    On Wed, 28 May 2025 14:41:56 +0200, David Brown
    <[email protected]> wrote:

    On 28/05/2025 01:13, Joe Gwinn wrote:
    On Tue, 27 May 2025 14:13:02 -0700, Don Y
    <[email protected]d> wrote:

    On 5/25/2025 12:33 PM, Joe Gwinn wrote:
    Exactly. I recall a customer wanting us to verify all possible paths
    through a bit of air traffic control radar software, about 100,000
    lines of plain C. Roughly one in five executable line was an IF
    statement, which is 20,000 IF statements. So there are 2^20000 =
    10^6020 such paths.

    And probably 99.9% of them are superfluous.

    [snip]

    The problem is that you have no way to know which cases are
    irrelevant. And practical hardware will have many things able to
    retain state.


    A concept you are looking for here is "cyclomatic complexity" :

    <https://en.wikipedia.org/wiki/Cyclomatic_complexity>

    Conditionals are not independent (in most cases) - thus the number of
    paths through code is not simply two to the power of the number of if >statements.

    True, but it's the bounding case.


    (McCabe cyclomatic complexity measures are not the only way to look at
    this, and like anything else, the measure has its advantages and >disadvantages, and is not suitable for everything. But it's a
    reasonable place to start.)

    The way you handle complexity in software is exactly the same as any
    other complexity - you break things down into manageable parts. For >software, that can be libraries, modules, files, classes, functions, and >blocks. You specify things from the top down, and test them from the
    bottom up. How much testing you do, and how you do it, is going to
    depend on the application - an air traffic control system will need more >thorough testing than a mobile phone game.

    When you are looking at a function, the cyclomatic complexity can be >calculated by tools. It will then give you a good idea of how much
    testing you need for the function. Too high a complexity, and you will
    never be able to test the function to get a solid idea of its
    correctness, as you would need too many test cases for practicality.
    (You may still be able to use other analysis methods.) The complexity
    can also give a good indication of how easy it is for humans to
    understand the function and judge its correctness. (Again, no one
    measure gives a complete picture.)

    I recall those days. Some managers thought that if they decreed that
    no module could have a complexity (computed in various ways) exceeding
    some arbitrary limit. The problem was that real-world problems are
    vastly more complex, causing atomization of the inherent complexity
    into a bazillion tiny modules, hiding the structure and imposing large
    added processing overheads from traversing all those inter-module
    interfaces.

    A parallel panacea was to mandate that the flowchart of <a software
    thing> be strictly planar, with no crossovers allowed. The hope was
    that with such a restriction it would be possible to create code
    correctness verification software. This also failed, because it's
    actually impossible to do (see the halting problem) and because the
    attempt is actually computationally intractable with non-toy examples.


    Other tools that can be useful in testing are code coverage tools - you
    can check that your test setups check all paths through the code.

    We still do this, but the limitation is that all such tools yield far
    more false alarms then valid hits, so all hits must be manually
    verified.


    But remember that testing cannot prove the absence of bugs - only their >presence. And it only works on the assumption that the hardware is
    correct - even when the software is perfect, you might still need that
    reset button or a watchdog!

    Absolutely. This was true in the days of uniprocessors with one
    megahertz clocks and kilobyte memories. Now it's hundreds of
    processors with multi-gigahertz clocks and terabyte physical memories.

    Joe Gwinn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Joe Gwinn on Fri May 30 17:53:59 2025
    On 28/05/2025 18:07, Joe Gwinn wrote:
    On Wed, 28 May 2025 14:41:56 +0200, David Brown
    <[email protected]> wrote:

    On 28/05/2025 01:13, Joe Gwinn wrote:
    On Tue, 27 May 2025 14:13:02 -0700, Don Y
    <[email protected]d> wrote:

    On 5/25/2025 12:33 PM, Joe Gwinn wrote:
    Exactly. I recall a customer wanting us to verify all possible paths >>>>> through a bit of air traffic control radar software, about 100,000
    lines of plain C. Roughly one in five executable line was an IF
    statement, which is 20,000 IF statements. So there are 2^20000 =
    10^6020 such paths.

    And probably 99.9% of them are superfluous.

    [snip]

    The problem is that you have no way to know which cases are
    irrelevant. And practical hardware will have many things able to
    retain state.


    A concept you are looking for here is "cyclomatic complexity" :

    <https://en.wikipedia.org/wiki/Cyclomatic_complexity>

    Conditionals are not independent (in most cases) - thus the number of
    paths through code is not simply two to the power of the number of if
    statements.

    True, but it's the bounding case.


    (McCabe cyclomatic complexity measures are not the only way to look at
    this, and like anything else, the measure has its advantages and
    disadvantages, and is not suitable for everything. But it's a
    reasonable place to start.)

    The way you handle complexity in software is exactly the same as any
    other complexity - you break things down into manageable parts. For
    software, that can be libraries, modules, files, classes, functions, and
    blocks. You specify things from the top down, and test them from the
    bottom up. How much testing you do, and how you do it, is going to
    depend on the application - an air traffic control system will need more
    thorough testing than a mobile phone game.

    When you are looking at a function, the cyclomatic complexity can be
    calculated by tools. It will then give you a good idea of how much
    testing you need for the function. Too high a complexity, and you will
    never be able to test the function to get a solid idea of its
    correctness, as you would need too many test cases for practicality.
    (You may still be able to use other analysis methods.) The complexity
    can also give a good indication of how easy it is for humans to
    understand the function and judge its correctness. (Again, no one
    measure gives a complete picture.)

    I recall those days. Some managers thought that if they decreed that
    no module could have a complexity (computed in various ways) exceeding
    some arbitrary limit. The problem was that real-world problems are
    vastly more complex, causing atomization of the inherent complexity
    into a bazillion tiny modules, hiding the structure and imposing large
    added processing overheads from traversing all those inter-module
    interfaces.


    The problem with any generalisation and rules is that they are sometimes inappropriate. /Most/ functions, modules, pages of schematic diagram,
    or whatever, should have a low complexity however you compute it. But
    there are always some that are exceptions, where the code is clearer
    despite being "complex" according to the metrics you use.


    Other tools that can be useful in testing are code coverage tools - you
    can check that your test setups check all paths through the code.

    We still do this, but the limitation is that all such tools yield far
    more false alarms then valid hits, so all hits must be manually
    verified.


    A false alarm for a code coverage report would mean code that is not
    reported as hit, but actually /is/ hit when the code is run. How does
    that come about?

    But it is certainly true that any kind of automatic testing or
    verification is only going to get you so far - false hits or missed
    cases are inevitable.


    But remember that testing cannot prove the absence of bugs - only their
    presence. And it only works on the assumption that the hardware is
    correct - even when the software is perfect, you might still need that
    reset button or a watchdog!

    Absolutely. This was true in the days of uniprocessors with one
    megahertz clocks and kilobyte memories. Now it's hundreds of
    processors with multi-gigahertz clocks and terabyte physical memories.


    And it's still true - modern systems give more scope for hardware issues
    than simpler systems (as well as more scope for subtle software bugs).
    A cosmic ray in the wrong place can render all your software
    verification void.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Joe Gwinn@21:1/5 to [email protected] on Fri May 30 13:39:51 2025
    On Fri, 30 May 2025 17:53:59 +0200, David Brown
    <[email protected]> wrote:

    On 28/05/2025 18:07, Joe Gwinn wrote:
    On Wed, 28 May 2025 14:41:56 +0200, David Brown
    <[email protected]> wrote:

    On 28/05/2025 01:13, Joe Gwinn wrote:
    On Tue, 27 May 2025 14:13:02 -0700, Don Y
    <[email protected]d> wrote:

    On 5/25/2025 12:33 PM, Joe Gwinn wrote:
    Exactly. I recall a customer wanting us to verify all possible paths >>>>>> through a bit of air traffic control radar software, about 100,000 >>>>>> lines of plain C. Roughly one in five executable line was an IF
    statement, which is 20,000 IF statements. So there are 2^20000 =
    10^6020 such paths.

    And probably 99.9% of them are superfluous.

    [snip]

    The problem is that you have no way to know which cases are
    irrelevant. And practical hardware will have many things able to
    retain state.


    A concept you are looking for here is "cyclomatic complexity" :

    <https://en.wikipedia.org/wiki/Cyclomatic_complexity>

    Conditionals are not independent (in most cases) - thus the number of
    paths through code is not simply two to the power of the number of if
    statements.

    True, but it's the bounding case.


    (McCabe cyclomatic complexity measures are not the only way to look at
    this, and like anything else, the measure has its advantages and
    disadvantages, and is not suitable for everything. But it's a
    reasonable place to start.)

    The way you handle complexity in software is exactly the same as any
    other complexity - you break things down into manageable parts. For
    software, that can be libraries, modules, files, classes, functions, and >>> blocks. You specify things from the top down, and test them from the
    bottom up. How much testing you do, and how you do it, is going to
    depend on the application - an air traffic control system will need more >>> thorough testing than a mobile phone game.

    When you are looking at a function, the cyclomatic complexity can be
    calculated by tools. It will then give you a good idea of how much
    testing you need for the function. Too high a complexity, and you will
    never be able to test the function to get a solid idea of its
    correctness, as you would need too many test cases for practicality.
    (You may still be able to use other analysis methods.) The complexity
    can also give a good indication of how easy it is for humans to
    understand the function and judge its correctness. (Again, no one
    measure gives a complete picture.)

    I recall those days. Some managers thought that if they decreed that
    no module could have a complexity (computed in various ways) exceeding
    some arbitrary limit. The problem was that real-world problems are
    vastly more complex, causing atomization of the inherent complexity
    into a bazillion tiny modules, hiding the structure and imposing large
    added processing overheads from traversing all those inter-module
    interfaces.


    The problem with any generalisation and rules is that they are sometimes >inappropriate. /Most/ functions, modules, pages of schematic diagram,
    or whatever, should have a low complexity however you compute it. But
    there are always some that are exceptions, where the code is clearer
    despite being "complex" according to the metrics you use.

    No, all of the complexity metrics were blown away by practical
    software running on practical hardware. Very few modules were that
    simple, because too many too small modules carry large inter-module
    interface overheads.


    Other tools that can be useful in testing are code coverage tools - you
    can check that your test setups check all paths through the code.

    We still do this, but the limitation is that all such tools yield far
    more false alarms then valid hits, so all hits must be manually
    verified.


    A false alarm for a code coverage report would mean code that is not
    reported as hit, but actually /is/ hit when the code is run. How does
    that come about?

    The code coverage vendors hold the details close, so we usually don't
    know how hits are declared, and probably never will.

    The one that I did manage to obtain the details turned out to be
    looking for certain combinations of certain words and arrangements. It
    had zero understanding of what the code did, never mind why.

    Maybe modern AI will do better, but may be too expensive to make
    business sense.


    But it is certainly true that any kind of automatic testing or
    verification is only going to get you so far - false hits or missed
    cases are inevitable.

    Yes, in fact the false hits dominate by a large factor, and the main
    expense in using such tools is the human effort needed to extract
    those few true hits.


    But remember that testing cannot prove the absence of bugs - only their
    presence. And it only works on the assumption that the hardware is
    correct - even when the software is perfect, you might still need that
    reset button or a watchdog!

    Absolutely. This was true in the days of uniprocessors with one
    megahertz clocks and kilobyte memories. Now it's hundreds of
    processors with multi-gigahertz clocks and terabyte physical memories.


    And it's still true - modern systems give more scope for hardware issues
    than simpler systems (as well as more scope for subtle software bugs).
    A cosmic ray in the wrong place can render all your software
    verification void.

    I must say that there was much worry about cosmic ray hits back in the
    day, but they never turned out to matter in practice, except in space
    systems.

    The dominant source of errors turned out to be electrical cross-talk
    and interference in the backplanes, and meta-stability in interfaces
    between logic clock domains in the larger hardware system.

    I vaguely recall doing an analysis on this issue, some decades ago.

    Joe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Joe Gwinn on Wed Jun 4 12:58:21 2025
    On 30/05/2025 19:39, Joe Gwinn wrote:
    On Fri, 30 May 2025 17:53:59 +0200, David Brown
    <[email protected]> wrote:

    On 28/05/2025 18:07, Joe Gwinn wrote:

    I recall those days. Some managers thought that if they decreed that
    no module could have a complexity (computed in various ways) exceeding
    some arbitrary limit. The problem was that real-world problems are
    vastly more complex, causing atomization of the inherent complexity
    into a bazillion tiny modules, hiding the structure and imposing large
    added processing overheads from traversing all those inter-module
    interfaces.


    The problem with any generalisation and rules is that they are sometimes
    inappropriate. /Most/ functions, modules, pages of schematic diagram,
    or whatever, should have a low complexity however you compute it. But
    there are always some that are exceptions, where the code is clearer
    despite being "complex" according to the metrics you use.

    No, all of the complexity metrics were blown away by practical
    software running on practical hardware. Very few modules were that
    simple, because too many too small modules carry large inter-module
    interface overheads.


    That changes nothing of the principles.

    You aim for low and controlled complexity, at all levels, so that you
    can realistically test, verify, and check the code and systems at the
    different levels. (Checking can be automatic, manual, human code
    reviews, code coverage tools, etc., - usually in combination.) Any part
    with particularly high complexity is going to take more specialised
    testing and checking - that costs more time and money, and is higher
    risk. Sometimes it is still the right choice, because alternatives are
    worse (such as the "too many small modules" issues you mention) or
    because there are clear and reliable ways to test dues to particular
    patterns (as you might get in a very large "dispatch" function).

    You don't just throw your hands in the air and say it's better with
    spaghetti in a module than spaghetti between modules, and therefore you
    can ignore complexity! I don't believe that is what you are actually
    doing, but it sounds a little like that.


    Other tools that can be useful in testing are code coverage tools - you >>>> can check that your test setups check all paths through the code.

    We still do this, but the limitation is that all such tools yield far
    more false alarms then valid hits, so all hits must be manually
    verified.


    A false alarm for a code coverage report would mean code that is not
    reported as hit, but actually /is/ hit when the code is run. How does
    that come about?

    The code coverage vendors hold the details close, so we usually don't
    know how hits are declared, and probably never will.


    Do the gcc and gcov developers hold their details secret? I'm sure
    there are many good reasons for picking different code coverage tools,
    and I'm not suggesting that gcov is in any way the "best" (for many
    reasons, code coverage tools would be of very limited use for most of my
    work). And there are all sorts of different coverage metrics. But it
    would surprise me if major vendors keep information about the prime
    purpose of the tool a secret. Who would buy a coverage tool that
    doesn't tell you what it measures?

    The one that I did manage to obtain the details turned out to be
    looking for certain combinations of certain words and arrangements. It
    had zero understanding of what the code did, never mind why.


    I am not sure what kind of tool you are referring to here. Code
    coverage tools track metrics about the functions, blocks and code lines
    that are run. Different tools (or options) track different metrics -
    counts, times, or just "at least once". They might track things at
    different levels. Some are intrusive and accurate, others are
    non-intrusive but statistical based. If you are wanting to use code
    coverage tools in combination with branch testing, you just want to know
    that during your test suite runs, every branch is tested at least once
    in each direction.

    Maybe modern AI will do better, but may be too expensive to make
    business sense.


    We can pretty much guarantee that commercial vendors will add claims of
    AI to their tools and charge more for them. Whether or not they will be
    better for it, is another matter.

    I would expect AI to be more useful in the context of static error
    checkers, simulators, and fuzz testers rather than code coverage at
    run-time.


    But it is certainly true that any kind of automatic testing or
    verification is only going to get you so far - false hits or missed
    cases are inevitable.

    Yes, in fact the false hits dominate by a large factor, and the main
    expense in using such tools is the human effort needed to extract
    those few true hits.


    Just to be clear - are you using non-intrusive statistical code coverage
    tools (i.e., a background thread, timer, etc., that samples the program
    counter of running code? Or are you using a tool that does
    instrumentation when compiling? I'm trying to get an understanding of
    the kinds of "false hits" you are seeing.



    But remember that testing cannot prove the absence of bugs - only their >>>> presence. And it only works on the assumption that the hardware is
    correct - even when the software is perfect, you might still need that >>>> reset button or a watchdog!

    Absolutely. This was true in the days of uniprocessors with one
    megahertz clocks and kilobyte memories. Now it's hundreds of
    processors with multi-gigahertz clocks and terabyte physical memories.


    And it's still true - modern systems give more scope for hardware issues
    than simpler systems (as well as more scope for subtle software bugs).
    A cosmic ray in the wrong place can render all your software
    verification void.

    I must say that there was much worry about cosmic ray hits back in the
    day, but they never turned out to matter in practice, except in space systems.

    I guess there are many factors for that. If something weird happens,
    and you have no explanation and it never happens again, then you can
    easily say it was probably a cosmic ray - without any direct evidence.
    It is also the case that many systems or subsystems are tolerant of an occasional single-event upset - be it from cosmic rays or anything else.
    If you have ECC memory, or other kinds of redundancy or error
    checking, rare errors there are not an issue. So many types of memory,
    buses, and communication protocols are effectively immune to such
    things. However, critical parts of the system will still be vulnerable
    to hardware glitches. It is not without justification that
    safety-critical electronics often has two cores running in lockstep or
    other types of redundancy.


    The dominant source of errors turned out to be electrical cross-talk
    and interference in the backplanes, and meta-stability in interfaces
    between logic clock domains in the larger hardware system.


    Sure. Cosmic rays were only an example (pulled out of thin air :.) ).
    Glitches on power lines, unlucky coincidences on bit patterns,
    production flaws or ESD damage eroding electrical tolerances - there are
    lots of possibilities. I'm not trying to suggest relative likelihoods
    here, as that will be highly variable.

    I vaguely recall doing an analysis on this issue, some decades ago.


    I recall something of the opposite - a long time ago, we had to add a
    variety of "safety" features to a product to fulfil a customer's safety
    / reliability checklist, without regard to how realistic the failure
    scenarios were and without spending time and money on analysis. The
    result was, IMHO, lower reliability because it was more likely for the
    extra monitoring and checking hardware and software to fail than for the original functional stuff to fail. Many of these extra checks were in themselves impossible to test.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Joe Gwinn@21:1/5 to [email protected] on Wed Jun 4 10:55:38 2025
    On Wed, 4 Jun 2025 12:58:21 +0200, David Brown
    <[email protected]> wrote:

    On 30/05/2025 19:39, Joe Gwinn wrote:
    On Fri, 30 May 2025 17:53:59 +0200, David Brown
    <[email protected]> wrote:

    On 28/05/2025 18:07, Joe Gwinn wrote:

    I recall those days. Some managers thought that if they decreed that
    no module could have a complexity (computed in various ways) exceeding >>>> some arbitrary limit. The problem was that real-world problems are
    vastly more complex, causing atomization of the inherent complexity
    into a bazillion tiny modules, hiding the structure and imposing large >>>> added processing overheads from traversing all those inter-module
    interfaces.


    The problem with any generalisation and rules is that they are sometimes >>> inappropriate. /Most/ functions, modules, pages of schematic diagram,
    or whatever, should have a low complexity however you compute it. But
    there are always some that are exceptions, where the code is clearer
    despite being "complex" according to the metrics you use.

    No, all of the complexity metrics were blown away by practical
    software running on practical hardware. Very few modules were that
    simple, because too many too small modules carry large inter-module
    interface overheads.


    That changes nothing of the principles.

    You aim for low and controlled complexity, at all levels, so that you
    can realistically test, verify, and check the code and systems at the >different levels. (Checking can be automatic, manual, human code
    reviews, code coverage tools, etc., - usually in combination.) Any part
    with particularly high complexity is going to take more specialised
    testing and checking - that costs more time and money, and is higher
    risk. Sometimes it is still the right choice, because alternatives are
    worse (such as the "too many small modules" issues you mention) or
    because there are clear and reliable ways to test dues to particular
    patterns (as you might get in a very large "dispatch" function).

    In theory, sure. In practice, it didn't help enough to make it
    worthwhile.


    You don't just throw your hands in the air and say it's better with
    spaghetti in a module than spaghetti between modules, and therefore you
    can ignore complexity! I don't believe that is what you are actually
    doing, but it sounds a little like that.

    Peer review of the code works better, because no pattern scanning tool
    can tell spaghetti from inherent complexity.

    And this goes double for operating system kernel code, which violate essentially all of the coding standards developed for user-level
    application code.


    Other tools that can be useful in testing are code coverage tools - you >>>>> can check that your test setups check all paths through the code.

    We still do this, but the limitation is that all such tools yield far
    more false alarms then valid hits, so all hits must be manually
    verified.


    A false alarm for a code coverage report would mean code that is not
    reported as hit, but actually /is/ hit when the code is run. How does
    that come about?

    The code coverage vendors hold the details close, so we usually don't
    know how hits are declared, and probably never will.


    Do the gcc and gcov developers hold their details secret? I'm sure
    there are many good reasons for picking different code coverage tools,
    and I'm not suggesting that gcov is in any way the "best" (for many
    reasons, code coverage tools would be of very limited use for most of my >work). And there are all sorts of different coverage metrics. But it
    would surprise me if major vendors keep information about the prime
    purpose of the tool a secret. Who would buy a coverage tool that
    doesn't tell you what it measures?

    I was dealing with a proprietary code coverage tool that management
    was quite enamored with and so was pressuring us to use. But we had
    only a sales brochure to go from, and I point-blank refused to use it
    without knowing what it did and how. This caused a copy of the
    requirements document of the scanner to appear.

    I don't think gcov existed then. We used gcc, so the software folk
    would have used it were it both available and mature enough.


    The one that I did manage to obtain the details turned out to be
    looking for certain combinations of certain words and arrangements. It
    had zero understanding of what the code did, never mind why.


    I am not sure what kind of tool you are referring to here.

    It's the proprietary coverage tool mentioned above.


    Code
    coverage tools track metrics about the functions, blocks and code lines
    that are run. Different tools (or options) track different metrics -
    counts, times, or just "at least once". They might track things at
    different levels. Some are intrusive and accurate, others are
    non-intrusive but statistical based. If you are wanting to use code
    coverage tools in combination with branch testing, you just want to know
    that during your test suite runs, every branch is tested at least once
    in each direction.

    Yep. The longer-term outlook is that this proprietary tool is just
    one of a stable of coverage tools that are used to generate lists for
    manual disposition by the authors of the code being scanned.


    Maybe modern AI will do better, but may be too expensive to make
    business sense.


    We can pretty much guarantee that commercial vendors will add claims of
    AI to their tools and charge more for them. Whether or not they will be >better for it, is another matter.

    Yes. Don't forget Quantum.


    I would expect AI to be more useful in the context of static error
    checkers, simulators, and fuzz testers rather than code coverage at
    run-time.

    Why? I would think that a LLM could follow the thread far better than
    any static checker.

    The US financial firm Morgan Stanley is using AI to analyze and
    summarize nine million lines of code (in languages such as COBOL) for re-implementation in modern languages. This from The Wall Street
    Journal, 3 June 2025 issue:

    "Morgan Stanley is now aiming artificial intelligence at one of
    enterprise software's biggest pain points, and one it said Big Tech
    hasn't quite nailed yet: helping rewrite old, outdated code into
    modern coding languages.

    In January, the company rolled out a tool known as DevGen.AI, built
    in-house on OpenAI's GPT models. It can translate legacy code from
    languages like COBOL into plain English specs that developers can then
    use to rewrite it.�

    So far this year it's reviewed nine million lines of code, saving
    developers 280,000 hours, said Mike Pizzi, Morgan Stanley's global
    head of technology and operations."


    But it is certainly true that any kind of automatic testing or
    verification is only going to get you so far - false hits or missed
    cases are inevitable.

    Yes, in fact the false hits dominate by a large factor, and the main
    expense in using such tools is the human effort needed to extract
    those few true hits.


    Just to be clear - are you using non-intrusive statistical code coverage >tools (i.e., a background thread, timer, etc., that samples the program >counter of running code? Or are you using a tool that does
    instrumentation when compiling? I'm trying to get an understanding of
    the kinds of "false hits" you are seeing.



    But remember that testing cannot prove the absence of bugs - only their >>>>> presence. And it only works on the assumption that the hardware is
    correct - even when the software is perfect, you might still need that >>>>> reset button or a watchdog!

    Absolutely. This was true in the days of uniprocessors with one
    megahertz clocks and kilobyte memories. Now it's hundreds of
    processors with multi-gigahertz clocks and terabyte physical memories. >>>>

    And it's still true - modern systems give more scope for hardware issues >>> than simpler systems (as well as more scope for subtle software bugs).
    A cosmic ray in the wrong place can render all your software
    verification void.

    I must say that there was much worry about cosmic ray hits back in the
    day, but they never turned out to matter in practice, except in space
    systems.

    I guess there are many factors for that. If something weird happens,
    and you have no explanation and it never happens again, then you can
    easily say it was probably a cosmic ray - without any direct evidence.
    It is also the case that many systems or subsystems are tolerant of an >occasional single-event upset - be it from cosmic rays or anything else.
    If you have ECC memory, or other kinds of redundancy or error
    checking, rare errors there are not an issue. So many types of memory, >buses, and communication protocols are effectively immune to such
    things. However, critical parts of the system will still be vulnerable
    to hardware glitches. It is not without justification that
    safety-critical electronics often has two cores running in lockstep or
    other types of redundancy.

    What happened is that semiconductor technology progressed to the point
    that the amount of charge (or whatever) that distinguished symbols
    became very small and thus vulnerable to random errors, for which an error-correcting code had to be built in. At this point, cosmic rays
    were lost in the random noise, so to speak. So ECC is now inherent,
    not an extra-cost bolt-on.


    The dominant source of errors turned out to be electrical cross-talk
    and interference in the backplanes, and meta-stability in interfaces
    between logic clock domains in the larger hardware system.


    Sure. Cosmic rays were only an example (pulled out of thin air :.) ). >Glitches on power lines, unlucky coincidences on bit patterns,
    production flaws or ESD damage eroding electrical tolerances - there are
    lots of possibilities. I'm not trying to suggest relative likelihoods
    here, as that will be highly variable.

    And this is still true.


    I vaguely recall doing an analysis on this issue, some decades ago.


    I recall something of the opposite - a long time ago, we had to add a
    variety of "safety" features to a product to fulfil a customer's safety
    / reliability checklist, without regard to how realistic the failure >scenarios were and without spending time and money on analysis. The
    result was, IMHO, lower reliability because it was more likely for the
    extra monitoring and checking hardware and software to fail than for the >original functional stuff to fail. Many of these extra checks were in >themselves impossible to test.

    Yes. I recall directly testing the issue with ECC as implemented in
    early DEC VAX computers, in the early 1980s. We had a customer who
    specified ECC, so we had ECC. And soon discovered that the computer
    was more reliable with ECC disabled than enabled. That was the end of
    ECC.

    Joe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Joe Gwinn on Wed Jun 4 17:53:19 2025
    On 04/06/2025 16:55, Joe Gwinn wrote:
    On Wed, 4 Jun 2025 12:58:21 +0200, David Brown
    <[email protected]> wrote:

    On 30/05/2025 19:39, Joe Gwinn wrote:
    On Fri, 30 May 2025 17:53:59 +0200, David Brown
    <[email protected]> wrote:

    On 28/05/2025 18:07, Joe Gwinn wrote:

    I recall those days. Some managers thought that if they decreed that >>>>> no module could have a complexity (computed in various ways) exceeding >>>>> some arbitrary limit. The problem was that real-world problems are
    vastly more complex, causing atomization of the inherent complexity
    into a bazillion tiny modules, hiding the structure and imposing large >>>>> added processing overheads from traversing all those inter-module
    interfaces.


    The problem with any generalisation and rules is that they are sometimes >>>> inappropriate. /Most/ functions, modules, pages of schematic diagram, >>>> or whatever, should have a low complexity however you compute it. But >>>> there are always some that are exceptions, where the code is clearer
    despite being "complex" according to the metrics you use.

    No, all of the complexity metrics were blown away by practical
    software running on practical hardware. Very few modules were that
    simple, because too many too small modules carry large inter-module
    interface overheads.


    That changes nothing of the principles.

    You aim for low and controlled complexity, at all levels, so that you
    can realistically test, verify, and check the code and systems at the
    different levels. (Checking can be automatic, manual, human code
    reviews, code coverage tools, etc., - usually in combination.) Any part
    with particularly high complexity is going to take more specialised
    testing and checking - that costs more time and money, and is higher
    risk. Sometimes it is still the right choice, because alternatives are
    worse (such as the "too many small modules" issues you mention) or
    because there are clear and reliable ways to test dues to particular
    patterns (as you might get in a very large "dispatch" function).

    In theory, sure. In practice, it didn't help enough to make it
    worthwhile.


    OK.


    You don't just throw your hands in the air and say it's better with
    spaghetti in a module than spaghetti between modules, and therefore you
    can ignore complexity! I don't believe that is what you are actually
    doing, but it sounds a little like that.

    Peer review of the code works better, because no pattern scanning tool
    can tell spaghetti from inherent complexity.


    That's certainly true in some cases. It surprises me a little that your experience was so much like that, but of course experiences differ. My experience (and I freely admit I haven't used complexity analysis tools
    much) is that most functions can be relatively low complexity - the
    inherently high complexity stuff is only a small proportion of the code.
    In one situation where this was not the case, I asked the programmer
    to re-structure the whole thing - the code was badly designed from the
    start and had become an incomprehensible mess. Peer review did not
    help, because the peer (me) couldn't figure out what was going on in the
    code.

    However, it is entirely true that some code will be marked as very high complexity by tools and yet easily and simply understood by human
    reviewers. If that is happening a lot in a code base, automatic tools
    (at least the ones you are trying) are not going to be much use.

    And this goes double for operating system kernel code, which violate essentially all of the coding standards developed for user-level
    application code.


    Different code has different needs and standards, yes.


    Other tools that can be useful in testing are code coverage tools - you >>>>>> can check that your test setups check all paths through the code.

    We still do this, but the limitation is that all such tools yield far >>>>> more false alarms then valid hits, so all hits must be manually
    verified.


    A false alarm for a code coverage report would mean code that is not
    reported as hit, but actually /is/ hit when the code is run. How does >>>> that come about?

    The code coverage vendors hold the details close, so we usually don't
    know how hits are declared, and probably never will.


    Do the gcc and gcov developers hold their details secret? I'm sure
    there are many good reasons for picking different code coverage tools,
    and I'm not suggesting that gcov is in any way the "best" (for many
    reasons, code coverage tools would be of very limited use for most of my
    work). And there are all sorts of different coverage metrics. But it
    would surprise me if major vendors keep information about the prime
    purpose of the tool a secret. Who would buy a coverage tool that
    doesn't tell you what it measures?

    I was dealing with a proprietary code coverage tool that management
    was quite enamored with and so was pressuring us to use. But we had
    only a sales brochure to go from, and I point-blank refused to use it
    without knowing what it did and how. This caused a copy of the
    requirements document of the scanner to appear.


    No software tool can fix management problems :-(

    I don't think gcov existed then. We used gcc, so the software folk
    would have used it were it both available and mature enough.


    Fair enough. I haven't done anything significant with gcov, so I can't
    say how good it might be. (It is very difficult to use tools that write
    data to files when you are working on small microcontrollers with no
    filesystem and at most a small RTOS.)

    Maybe modern AI will do better, but may be too expensive to make
    business sense.


    We can pretty much guarantee that commercial vendors will add claims of
    AI to their tools and charge more for them. Whether or not they will be
    better for it, is another matter.

    Yes. Don't forget Quantum.

    We are already into post-quantum algorithms, at least in some fields!



    I would expect AI to be more useful in the context of static error
    checkers, simulators, and fuzz testers rather than code coverage at
    run-time.

    Why? I would think that a LLM could follow the thread far better than
    any static checker.


    I mean that I think there is more potential for adding useful AI
    algorithms to static checkers and simulators than there is for using AI algorithms in run-time code coverage tools. But that's just a guess,
    not backed up by any evidence.

    The US financial firm Morgan Stanley is using AI to analyze and
    summarize nine million lines of code (in languages such as COBOL) for re-implementation in modern languages. This from The Wall Street
    Journal, 3 June 2025 issue:

    "Morgan Stanley is now aiming artificial intelligence at one of
    enterprise software's biggest pain points, and one it said Big Tech
    hasn't quite nailed yet: helping rewrite old, outdated code into
    modern coding languages.

    I can see AI being a help here - just as many existing tools can be
    helpful for figuring out what old code does. I am not holding my breath waiting for AI to manage such conversions on its own.


    In January, the company rolled out a tool known as DevGen.AI, built
    in-house on OpenAI's GPT models. It can translate legacy code from
    languages like COBOL into plain English specs that developers can then
    use to rewrite it.

    So far this year it's reviewed nine million lines of code, saving
    developers 280,000 hours, said Mike Pizzi, Morgan Stanley's global
    head of technology and operations."




    And it's still true - modern systems give more scope for hardware issues >>>> than simpler systems (as well as more scope for subtle software bugs). >>>> A cosmic ray in the wrong place can render all your software
    verification void.

    I must say that there was much worry about cosmic ray hits back in the
    day, but they never turned out to matter in practice, except in space
    systems.

    I guess there are many factors for that. If something weird happens,
    and you have no explanation and it never happens again, then you can
    easily say it was probably a cosmic ray - without any direct evidence.
    It is also the case that many systems or subsystems are tolerant of an
    occasional single-event upset - be it from cosmic rays or anything else.
    If you have ECC memory, or other kinds of redundancy or error
    checking, rare errors there are not an issue. So many types of memory,
    buses, and communication protocols are effectively immune to such
    things. However, critical parts of the system will still be vulnerable
    to hardware glitches. It is not without justification that
    safety-critical electronics often has two cores running in lockstep or
    other types of redundancy.

    What happened is that semiconductor technology progressed to the point
    that the amount of charge (or whatever) that distinguished symbols
    became very small and thus vulnerable to random errors, for which an error-correcting code had to be built in. At this point, cosmic rays
    were lost in the random noise, so to speak. So ECC is now inherent,
    not an extra-cost bolt-on.


    For very dense and small feature size electronics, that is mostly true -
    though even then there are parts that are vulnerable. It's just that
    those parts are a tiny proportion of the die size, compared to memory
    arrays, and the like.


    The dominant source of errors turned out to be electrical cross-talk
    and interference in the backplanes, and meta-stability in interfaces
    between logic clock domains in the larger hardware system.


    Sure. Cosmic rays were only an example (pulled out of thin air :.) ).
    Glitches on power lines, unlucky coincidences on bit patterns,
    production flaws or ESD damage eroding electrical tolerances - there are
    lots of possibilities. I'm not trying to suggest relative likelihoods
    here, as that will be highly variable.

    And this is still true.


    I vaguely recall doing an analysis on this issue, some decades ago.


    I recall something of the opposite - a long time ago, we had to add a
    variety of "safety" features to a product to fulfil a customer's safety
    / reliability checklist, without regard to how realistic the failure
    scenarios were and without spending time and money on analysis. The
    result was, IMHO, lower reliability because it was more likely for the
    extra monitoring and checking hardware and software to fail than for the
    original functional stuff to fail. Many of these extra checks were in
    themselves impossible to test.

    Yes. I recall directly testing the issue with ECC as implemented in
    early DEC VAX computers, in the early 1980s. We had a customer who
    specified ECC, so we had ECC. And soon discovered that the computer
    was more reliable with ECC disabled than enabled. That was the end of
    ECC.


    Quis custodiet ipsos custodes?

    Sometimes these fault monitors and error checking systems are just
    kicking the can further down the road, and not actually improving anything.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Joe Gwinn@21:1/5 to [email protected] on Wed Jun 4 14:54:30 2025
    On Wed, 4 Jun 2025 17:53:19 +0200, David Brown
    <[email protected]> wrote:

    On 04/06/2025 16:55, Joe Gwinn wrote:
    On Wed, 4 Jun 2025 12:58:21 +0200, David Brown
    <[email protected]> wrote:

    On 30/05/2025 19:39, Joe Gwinn wrote:
    On Fri, 30 May 2025 17:53:59 +0200, David Brown
    <[email protected]> wrote:

    On 28/05/2025 18:07, Joe Gwinn wrote:

    I recall those days. Some managers thought that if they decreed that >>>>>> no module could have a complexity (computed in various ways) exceeding >>>>>> some arbitrary limit. The problem was that real-world problems are >>>>>> vastly more complex, causing atomization of the inherent complexity >>>>>> into a bazillion tiny modules, hiding the structure and imposing large >>>>>> added processing overheads from traversing all those inter-module
    interfaces.


    The problem with any generalisation and rules is that they are sometimes >>>>> inappropriate. /Most/ functions, modules, pages of schematic diagram, >>>>> or whatever, should have a low complexity however you compute it. But >>>>> there are always some that are exceptions, where the code is clearer >>>>> despite being "complex" according to the metrics you use.

    No, all of the complexity metrics were blown away by practical
    software running on practical hardware. Very few modules were that
    simple, because too many too small modules carry large inter-module
    interface overheads.


    That changes nothing of the principles.

    You aim for low and controlled complexity, at all levels, so that you
    can realistically test, verify, and check the code and systems at the
    different levels. (Checking can be automatic, manual, human code
    reviews, code coverage tools, etc., - usually in combination.) Any part >>> with particularly high complexity is going to take more specialised
    testing and checking - that costs more time and money, and is higher
    risk. Sometimes it is still the right choice, because alternatives are
    worse (such as the "too many small modules" issues you mention) or
    because there are clear and reliable ways to test dues to particular
    patterns (as you might get in a very large "dispatch" function).

    In theory, sure. In practice, it didn't help enough to make it
    worthwhile.


    OK.


    You don't just throw your hands in the air and say it's better with
    spaghetti in a module than spaghetti between modules, and therefore you
    can ignore complexity! I don't believe that is what you are actually
    doing, but it sounds a little like that.

    Peer review of the code works better, because no pattern scanning tool
    can tell spaghetti from inherent complexity.


    That's certainly true in some cases. It surprises me a little that your >experience was so much like that, but of course experiences differ. My >experience (and I freely admit I haven't used complexity analysis tools
    much) is that most functions can be relatively low complexity - the >inherently high complexity stuff is only a small proportion of the code.
    In one situation where this was not the case, I asked the programmer
    to re-structure the whole thing - the code was badly designed from the
    start and had become an incomprehensible mess. Peer review did not
    help, because the peer (me) couldn't figure out what was going on in the >code.

    All true, but at the end of the day, complexity metrics and coverage
    tools didn't come even close to paying for itself, and so they
    gradually faded.


    However, it is entirely true that some code will be marked as very high >complexity by tools and yet easily and simply understood by human
    reviewers. If that is happening a lot in a code base, automatic tools
    (at least the ones you are trying) are not going to be much use.

    The issue is not human understanding per se, it's human effort.


    And this goes double for operating system kernel code, which violate
    essentially all of the coding standards developed for user-level
    application code.


    Different code has different needs and standards, yes.


    Other tools that can be useful in testing are code coverage tools - you >>>>>>> can check that your test setups check all paths through the code. >>>>>>
    We still do this, but the limitation is that all such tools yield far >>>>>> more false alarms then valid hits, so all hits must be manually
    verified.


    A false alarm for a code coverage report would mean code that is not >>>>> reported as hit, but actually /is/ hit when the code is run. How does >>>>> that come about?

    The code coverage vendors hold the details close, so we usually don't
    know how hits are declared, and probably never will.


    Do the gcc and gcov developers hold their details secret? I'm sure
    there are many good reasons for picking different code coverage tools,
    and I'm not suggesting that gcov is in any way the "best" (for many
    reasons, code coverage tools would be of very limited use for most of my >>> work). And there are all sorts of different coverage metrics. But it
    would surprise me if major vendors keep information about the prime
    purpose of the tool a secret. Who would buy a coverage tool that
    doesn't tell you what it measures?

    I was dealing with a proprietary code coverage tool that management
    was quite enamored with and so was pressuring us to use. But we had
    only a sales brochure to go from, and I point-blank refused to use it
    without knowing what it did and how. This caused a copy of the
    requirements document of the scanner to appear.


    No software tool can fix management problems :-(

    I don't think gcov existed then. We used gcc, so the software folk
    would have used it were it both available and mature enough.


    Fair enough. I haven't done anything significant with gcov, so I can't
    say how good it might be. (It is very difficult to use tools that write
    data to files when you are working on small microcontrollers with no >filesystem and at most a small RTOS.)

    In those cases, the development computers were far larger than the
    target systems.


    Maybe modern AI will do better, but may be too expensive to make
    business sense.


    We can pretty much guarantee that commercial vendors will add claims of
    AI to their tools and charge more for them. Whether or not they will be >>> better for it, is another matter.

    Yes. Don't forget Quantum.

    We are already into post-quantum algorithms, at least in some fields!



    I would expect AI to be more useful in the context of static error
    checkers, simulators, and fuzz testers rather than code coverage at
    run-time.

    Forgotten from earlier: "Just to be clear - are you using
    non-intrusive statistical code coverage tools (i.e., a background
    thread, timer, etc., that samples the program counter of running code?
    Or are you using a tool that does instrumentation when compiling? I'm
    trying to get an understanding of the kinds of "false hits" you are
    seeing."

    The focus here is non-intrusive code evaluation tools.

    We also use intrusive tools and instrumentation in the integration
    lab.


    Why (AI)? I would think that a LLM could follow the thread far better than >> any static checker.


    I mean that I think there is more potential for adding useful AI
    algorithms to static checkers and simulators than there is for using AI >algorithms in run-time code coverage tools. But that's just a guess,
    not backed up by any evidence.

    The US financial firm Morgan Stanley is using AI to analyze and
    summarize nine million lines of code (in languages such as COBOL) for
    re-implementation in modern languages. This from The Wall Street
    Journal, 3 June 2025 issue:

    "Morgan Stanley is now aiming artificial intelligence at one of
    enterprise software's biggest pain points, and one it said Big Tech
    hasn't quite nailed yet: helping rewrite old, outdated code into
    modern coding languages.

    I can see AI being a help here - just as many existing tools can be
    helpful for figuring out what old code does. I am not holding my breath >waiting for AI to manage such conversions on its own.

    Nor is MS - the new code is written by humans.

    Although MS is trying automatic translation into modern languages, I
    gather that it doesn't work all that well. In my world, there was a
    lot of talk of building automatic converters to translate from one
    computer language to another. It never worked because no machine
    could understand the inventive ways people on tiny machines used
    bespoke memory structures to improve performance.


    War story: In the 1970s, I was involved in writing Fortran code to
    implement a simulator used for training. This required 32-bit words
    used as bit arrays, but the Fortran of the day had no bitwise
    operation, only one bit per word logic. Which was crippling, so I
    wrote an assembly-coded Fortran function that did the bitwise
    operation expressions needed for this and that.

    Our application programmers were intimidated by being asked to write a
    little assembly, but I had set it up so they could easily do it, once
    the shock wore off. It all worked.

    Thirty years later, I got a phone call from the blue from someone in a
    company that had won a contract to recode the simulator code in C
    wondering what to do with those assembly-coded functions. He was very
    relieved when I said that if the ISA library had been available, we
    would have used that, and to just read the assembly source to find the
    bitwise operations being performed, and write that directly in C.


    In January, the company rolled out a tool known as DevGen.AI, built
    in-house on OpenAI's GPT models. It can translate legacy code from
    languages like COBOL into plain English specs that developers can then
    use to rewrite it.

    So far this year it's reviewed nine million lines of code, saving
    developers 280,000 hours, said Mike Pizzi, Morgan Stanley's global
    head of technology and operations."

    The 280,000 hours of saved labor is why this will continue.



    And it's still true - modern systems give more scope for hardware issues >>>>> than simpler systems (as well as more scope for subtle software bugs). >>>>> A cosmic ray in the wrong place can render all your software
    verification void.

    I must say that there was much worry about cosmic ray hits back in the >>>> day, but they never turned out to matter in practice, except in space
    systems.

    I guess there are many factors for that. If something weird happens,
    and you have no explanation and it never happens again, then you can
    easily say it was probably a cosmic ray - without any direct evidence.
    It is also the case that many systems or subsystems are tolerant of an
    occasional single-event upset - be it from cosmic rays or anything else. >>> If you have ECC memory, or other kinds of redundancy or error
    checking, rare errors there are not an issue. So many types of memory,
    buses, and communication protocols are effectively immune to such
    things. However, critical parts of the system will still be vulnerable
    to hardware glitches. It is not without justification that
    safety-critical electronics often has two cores running in lockstep or
    other types of redundancy.

    What happened is that semiconductor technology progressed to the point
    that the amount of charge (or whatever) that distinguished symbols
    became very small and thus vulnerable to random errors, for which an
    error-correcting code had to be built in. At this point, cosmic rays
    were lost in the random noise, so to speak. So ECC is now inherent,
    not an extra-cost bolt-on.


    For very dense and small feature size electronics, that is mostly true - >though even then there are parts that are vulnerable. It's just that
    those parts are a tiny proportion of the die size, compared to memory
    arrays, and the like.


    The dominant source of errors turned out to be electrical cross-talk
    and interference in the backplanes, and meta-stability in interfaces
    between logic clock domains in the larger hardware system.


    Sure. Cosmic rays were only an example (pulled out of thin air :.) ).
    Glitches on power lines, unlucky coincidences on bit patterns,
    production flaws or ESD damage eroding electrical tolerances - there are >>> lots of possibilities. I'm not trying to suggest relative likelihoods
    here, as that will be highly variable.

    And this is still true.


    I vaguely recall doing an analysis on this issue, some decades ago.


    I recall something of the opposite - a long time ago, we had to add a
    variety of "safety" features to a product to fulfil a customer's safety
    / reliability checklist, without regard to how realistic the failure
    scenarios were and without spending time and money on analysis. The
    result was, IMHO, lower reliability because it was more likely for the
    extra monitoring and checking hardware and software to fail than for the >>> original functional stuff to fail. Many of these extra checks were in
    themselves impossible to test.

    Yes. I recall directly testing the issue with ECC as implemented in
    early DEC VAX computers, in the early 1980s. We had a customer who
    specified ECC, so we had ECC. And soon discovered that the computer
    was more reliable with ECC disabled than enabled. That was the end of
    ECC.


    Quis custodiet ipsos custodes?

    Sometimes these fault monitors and error checking systems are just
    kicking the can further down the road, and not actually improving anything.

    Yes.

    Joe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Joe Gwinn on Thu Jun 5 09:42:44 2025
    On 04/06/2025 20:54, Joe Gwinn wrote:
    On Wed, 4 Jun 2025 17:53:19 +0200, David Brown
    <[email protected]> wrote:

    On 04/06/2025 16:55, Joe Gwinn wrote:
    On Wed, 4 Jun 2025 12:58:21 +0200, David Brown
    <[email protected]> wrote:




    All true, but at the end of the day, complexity metrics and coverage
    tools didn't come even close to paying for itself, and so they
    gradually faded.


    Fair enough. Even with open source tools where there is usually little
    or no up-front capital cost, there can still be significant costs in
    time and effort.

    Of course that does not mean that complexity should be ignored - it just
    means that you deal with it in other ways, such as getting in the habit
    of not writing overly complex code in the first place!


    Fair enough. I haven't done anything significant with gcov, so I can't
    say how good it might be. (It is very difficult to use tools that write
    data to files when you are working on small microcontrollers with no
    filesystem and at most a small RTOS.)

    In those cases, the development computers were far larger than the
    target systems.


    Indeed they are - and you have significantly different methods for
    developing, debugging and testing the code.


    Why (AI)? I would think that a LLM could follow the thread far better than >>> any static checker.


    I mean that I think there is more potential for adding useful AI
    algorithms to static checkers and simulators than there is for using AI
    algorithms in run-time code coverage tools. But that's just a guess,
    not backed up by any evidence.

    The US financial firm Morgan Stanley is using AI to analyze and
    summarize nine million lines of code (in languages such as COBOL) for
    re-implementation in modern languages. This from The Wall Street
    Journal, 3 June 2025 issue:

    "Morgan Stanley is now aiming artificial intelligence at one of
    enterprise software's biggest pain points, and one it said Big Tech
    hasn't quite nailed yet: helping rewrite old, outdated code into
    modern coding languages.

    I can see AI being a help here - just as many existing tools can be
    helpful for figuring out what old code does. I am not holding my breath
    waiting for AI to manage such conversions on its own.

    Nor is MS - the new code is written by humans.

    Although MS is trying automatic translation into modern languages, I
    gather that it doesn't work all that well. In my world, there was a
    lot of talk of building automatic converters to translate from one
    computer language to another. It never worked because no machine
    could understand the inventive ways people on tiny machines used
    bespoke memory structures to improve performance.


    Automatic translation between programming languages is unlikely to be successful unless the languages have very similar structures (say,
    Pascal to C) or you are using the output just as an intermediary
    language for compilation rather than as a new version of the program
    (like using cfront for C++ to C transcompilation). Good code written in
    one language is going to be structured differently from good code
    written in a different programming language. And these old code bases
    might have started as a "good code" at one time - they are very unlikely
    to have remained so over decades of fiddling, fixing and expanding.


    War story: In the 1970s, I was involved in writing Fortran code to
    implement a simulator used for training. This required 32-bit words
    used as bit arrays, but the Fortran of the day had no bitwise
    operation, only one bit per word logic. Which was crippling, so I
    wrote an assembly-coded Fortran function that did the bitwise
    operation expressions needed for this and that.

    Our application programmers were intimidated by being asked to write a
    little assembly, but I had set it up so they could easily do it, once
    the shock wore off. It all worked.

    Thirty years later, I got a phone call from the blue from someone in a company that had won a contract to recode the simulator code in C
    wondering what to do with those assembly-coded functions. He was very relieved when I said that if the ISA library had been available, we
    would have used that, and to just read the assembly source to find the bitwise operations being performed, and write that directly in C.



    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Martin Brown@21:1/5 to Joe Gwinn on Thu Jun 5 09:36:10 2025
    On 04/06/2025 19:54, Joe Gwinn wrote:
    On Wed, 4 Jun 2025 17:53:19 +0200, David Brown
    <[email protected]> wrote:

    On 04/06/2025 16:55, Joe Gwinn wrote:

    Peer review of the code works better, because no pattern scanning tool
    can tell spaghetti from inherent complexity.


    That's certainly true in some cases. It surprises me a little that your
    experience was so much like that, but of course experiences differ. My
    experience (and I freely admit I haven't used complexity analysis tools
    much) is that most functions can be relatively low complexity - the
    inherently high complexity stuff is only a small proportion of the code.
    In one situation where this was not the case, I asked the programmer
    to re-structure the whole thing - the code was badly designed from the
    start and had become an incomprehensible mess. Peer review did not
    help, because the peer (me) couldn't figure out what was going on in the
    code.

    All true, but at the end of the day, complexity metrics and coverage
    tools didn't come even close to paying for itself, and so they
    gradually faded.

    Complexity metrics and dataflow analysis tools worked OK for me when
    working as a consultant digging companies out of deep holes they had got themselves into. They invariably looked hurt at the long list of defects
    that I would find almost immediately and I was almost always right about
    code with an insane value for McCabe's CCI being full of latent bugs.

    Some code is irreversibly complex and necessarily so, but a lot of it is
    just the software equivalent of a rats nest prototype in electronics but treated as if it was production quality code. Management's ship it and
    be damned policy since they always wanted their sales target bonus.

    However, it is entirely true that some code will be marked as very high
    complexity by tools and yet easily and simply understood by human
    reviewers. If that is happening a lot in a code base, automatic tools
    (at least the ones you are trying) are not going to be much use.

    That goes with the territory but you only have to look at it once.
    I would expect AI to be more useful in the context of static error
    checkers, simulators, and fuzz testers rather than code coverage at
    run-time.

    Forgotten from earlier: "Just to be clear - are you using
    non-intrusive statistical code coverage tools (i.e., a background
    thread, timer, etc., that samples the program counter of running code?
    Or are you using a tool that does instrumentation when compiling? I'm
    trying to get an understanding of the kinds of "false hits" you are
    seeing."

    The focus here is non-intrusive code evaluation tools.

    We also use intrusive tools and instrumentation in the integration
    lab.

    I find instrumentation often disturbs the problem that I am looking at. YMMV

    I'm a fan of Intel's vTune for finding hotspots in serious code.

    --
    Martin Brown

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Carlos E.R.@21:1/5 to David Brown on Thu Jun 5 13:59:04 2025
    On 2025-06-05 09:42, David Brown wrote:
    On 04/06/2025 20:54, Joe Gwinn wrote:
    On Wed, 4 Jun 2025 17:53:19 +0200, David Brown
    <[email protected]> wrote:


    ...

    I can see AI being a help here - just as many existing tools can be
    helpful for figuring out what old code does.  I am not holding my breath >>> waiting for AI to manage such conversions on its own.

    Nor is MS - the new code is written by humans.

    Although MS is trying automatic translation into modern languages, I
    gather that it doesn't work all that well.  In my world, there was a
    lot of talk of building automatic converters to translate from one
    computer language to another.  It never worked because no machine
    could understand the inventive ways people on tiny machines used
    bespoke memory structures to improve performance.


    Automatic translation between programming languages is unlikely to be successful unless the languages have very similar structures (say,
    Pascal to C) or you are using the output just as an intermediary
    language for compilation rather than as a new version of the program
    (like using cfront for C++ to C transcompilation).  Good code written in
    one language is going to be structured differently from good code
    written in a different programming language.  And these old code bases
    might have started as a "good code" at one time - they are very unlikely
    to have remained so over decades of fiddling, fixing and expanding.

    Long ago I worked with an early version of LabWindows for MsDOS (around
    1995). You could create the program in Basic or C, and it could be
    translated back to the other language automatically. Specially in C the
    set was limited, though. Using the internal editor it worked.

    --
    Cheers, Carlos.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Joe Gwinn@21:1/5 to '''newspam'''@nonad.co.uk on Thu Jun 5 13:18:41 2025
    On Thu, 5 Jun 2025 09:36:10 +0100, Martin Brown
    <'''newspam'''@nonad.co.uk> wrote:

    On 04/06/2025 19:54, Joe Gwinn wrote:
    On Wed, 4 Jun 2025 17:53:19 +0200, David Brown
    <[email protected]> wrote:

    On 04/06/2025 16:55, Joe Gwinn wrote:

    Peer review of the code works better, because no pattern scanning tool >>>> can tell spaghetti from inherent complexity.


    That's certainly true in some cases. It surprises me a little that your >>> experience was so much like that, but of course experiences differ. My
    experience (and I freely admit I haven't used complexity analysis tools
    much) is that most functions can be relatively low complexity - the
    inherently high complexity stuff is only a small proportion of the code. >>> In one situation where this was not the case, I asked the programmer
    to re-structure the whole thing - the code was badly designed from the
    start and had become an incomprehensible mess. Peer review did not
    help, because the peer (me) couldn't figure out what was going on in the >>> code.

    All true, but at the end of the day, complexity metrics and coverage
    tools didn't come even close to paying for itself, and so they
    gradually faded.

    Complexity metrics and dataflow analysis tools worked OK for me when
    working as a consultant digging companies out of deep holes they had got >themselves into. They invariably looked hurt at the long list of defects
    that I would find almost immediately and I was almost always right about
    code with an insane value for McCabe's CCI being full of latent bugs.

    Yes. BTDT. The problem there is accidental complexity.

    In my world, requirements that I wrote years before will pop up in inappropriate places, but nobody understands them or how they got
    there, so the people implementing those requirements are rightly
    afraid to touch anything. So one of my unspoken tasks is to delete
    stray requirements. The savings can be quite substantial.

    Then there programmers in above their head.


    Some code is irreversibly complex and necessarily so, but a lot of it is
    just the software equivalent of a rats nest prototype in electronics but >treated as if it was production quality code. Management's ship it and
    be damned policy since they always wanted their sales target bonus.

    Yep. One thing I learned the hard way when still young was to always
    prototype in a convenient language unrelated to the language of the
    delivered project, precisely to prevent that abuse.


    However, it is entirely true that some code will be marked as very high
    complexity by tools and yet easily and simply understood by human
    reviewers. If that is happening a lot in a code base, automatic tools
    (at least the ones you are trying) are not going to be much use.

    That goes with the territory but you only have to look at it once.

    True, but it's still an investment decision - does this approach
    result in worthwhile savings? Or should the effort be spent
    elsewhere?


    I would expect AI to be more useful in the context of static error
    checkers, simulators, and fuzz testers rather than code coverage at
    run-time.

    Forgotten from earlier: "Just to be clear - are you using
    non-intrusive statistical code coverage tools (i.e., a background
    thread, timer, etc., that samples the program counter of running code?
    Or are you using a tool that does instrumentation when compiling? I'm
    trying to get an understanding of the kinds of "false hits" you are
    seeing."

    The focus here is non-intrusive code evaluation tools.

    We also use intrusive tools and instrumentation in the integration
    lab.

    I find instrumentation often disturbs the problem that I am looking at. YMMV

    This is very much a significant problem. My approach, unloved by
    process and language bigots alike, is to manually write the wiretap
    points in assembly code that rides the iron, invoking plain C (not
    C++) only if the wiretap decides to collect something. This is done
    because there are many more wiretaps in place than can be collected at
    once, so the decision to collect must be very quick.

    Which wiretaps are active is determined by a big bitmap array at a
    static location in memory.

    One form of wiretap checks for violation of a pre-specified assertion, collecting only on violation. This part is usually coded in plain C.
    Again, this must be quick, because assertions usually don't fail later
    during integration.

    Analysis of the collected data is wholly offline.


    I'm a fan of Intel's vTune for finding hotspots in serious code.

    This is after my time in the integration lab, but I'm curious.

    What I used was a special assembly-coded ISR triggered by a CPU timer
    register. The time period was chosen to be mutually prime with all
    significant periods in the kernel, application, or library code. This
    ISR took a snapshot of the memory addresses that were executing when
    the ISR ran. This data was histogrammed, and the peaks chase back to
    locations in the software.

    This was very useful on Ada83 projects, where lots of problems were
    because something that looks clean and simple actually mapped to a
    clumsy bit of Ada runtime system code - no amount of expert code
    review was going to figure this out. Once the problem was understood,
    we were able to paraphrase our way out of trouble, usually only by
    total avoidance of major parts of the language.

    Joe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Don Y@21:1/5 to Martin Brown on Thu Jun 5 12:34:52 2025
    On 6/5/2025 1:36 AM, Martin Brown wrote:
    Some code is irreversibly complex and necessarily so, but a lot of it is just the software equivalent of a rats nest prototype in electronics but treated as
    if it was production quality code. Management's ship it and be damned policy since they always wanted their sales target bonus.

    If you look at the *process* used by most shops to create software, there
    is very little discipline -- or, overly much (e.g., DoD). Both extremes
    leave the developer(s) floundering; the coder who is "playing it by ear" (without a formal specification telling him EXACTLY what he is developing
    and EXACTLY the criteria that will be tested/validated) and the one who
    is so far removed from the function of the product that he has little
    insight into what might be wrong about the specification that's been imposed
    on him.

    Blame the powers that be in both cases. Often, folks who have been promoted
    to their level of incompetence (Peter Principle)

    However, it is entirely true that some code will be marked as very high
    complexity by tools and yet easily and simply understood by human
    reviewers.  If that is happening a lot in a code base, automatic tools
    (at least the ones you are trying) are not going to be much use.

    That goes with the territory but you only have to look at it once.

    If the code has a formal specification, then you have a set of test
    criteria that come with the territory. And, solvers (e.g., KLEE)
    that can look for holes in the implementation.

    I would expect AI to be more useful in the context of static error
    checkers, simulators, and fuzz testers rather than code coverage at
    run-time.

    Forgotten from earlier: "Just to be clear - are you using
    non-intrusive statistical code coverage tools (i.e., a background
    thread, timer, etc., that samples the program counter of running code?
    Or are you using a tool that does instrumentation when compiling?  I'm
    trying to get an understanding of the kinds of "false hits" you are
    seeing."

    The focus here is non-intrusive code evaluation tools.

    We also use intrusive tools and instrumentation in the integration
    lab.

    I find instrumentation often disturbs the problem that I am looking at. YMMV

    Analyzing a "textual representation" leaves too many possibilities for
    reality to differ from theory.

    Are you 100% sure the compiler is bug free?

    Do you completely understand the execution environment (e.g., multithreading and multiprocessing) and the hazzards it creates?

    Are you sure the textual description of the solution (program) fits the
    actual problem model?

    Are you sure the developed model reflects the reality of the application?

    Are you sure the opcode fetched from memory *now* is exactly the one
    that the compiler placed, there? Ditto for data?

    I'm a fan of Intel's vTune for finding hotspots in serious code.

    I litter code with invariants -- and leave them in the production release (changing the FAIL case to panic()). The cost (space and time) is relatively insignificant. The reassurance it provides (when "can't happen" actually
    DOES happen!) far outweighs the burden on the product's performance.

    If you are "sure" of something, then you shouldn't have any problem making
    that declaration in the codebase. Then, if your assumption is proven wrong, you have positive evidence of it -- instead of wondering why it did something unexpected.

    By far, the problems I see in most products are poorly defined models.

    E.g., we have a stove/oven with a "big knob" UI: spin to choose from
    a list of values; press to make the selection. Trivial to implement.
    *Appears* to handle all cases (it doesn't). Easy to verify -- as a
    stand-alone module.

    The problem comes when you put that module into a device that has multiple processes running concurrently. E.g., there are two ovens, each with a
    cooking mode and temperature constraints. PLUS, individual timers to
    limit the operation. Plus another general purpose timer.

    But, only one UI ("big knob"). So, if the user is engaged with the UI
    (e.g., to set or alter the operating conditions of one of the ovens
    OR the timer) and one of the processes (oven 1, oven 2, timer) needs
    attention, there's only one way to talk to that process (big knob) but
    that is "busy" with some other activity.

    As a result, you end up "STOPping" the process (e.g., turn off the oven)
    and then restarting it -- just to disconnect the UI from the process
    that was in use when the "other" process called for service.

    I can just see the developer "proving" that his implementation worked -- one process at a time: "See, this is how you select CONVECTION instead of
    BAKE; and this is how you specify the temperature; and the cook time;
    and what to do when that time is expired; and how to START the process!"
    But, clearly never tried to actually *use* that while other processes were active in the device.

    These sorts of bugs have to be caught at the specification level; by
    someone *designing* the model instead of just naively implementing a
    part of it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to [email protected] on Fri Jun 6 13:45:02 2025
    In article <101p8sd$phe5$[email protected]>,
    David Brown <[email protected]> wrote:
    <SNIP>
    I recall something of the opposite - a long time ago, we had to add a
    variety of "safety" features to a product to fulfil a customer's safety
    / reliability checklist, without regard to how realistic the failure >scenarios were and without spending time and money on analysis. The
    result was, IMHO, lower reliability because it was more likely for the
    extra monitoring and checking hardware and software to fail than for the >original functional stuff to fail. Many of these extra checks were in >themselves impossible to test.

    I worked on the Dutch railway systems safety and control software.
    Once they added external control checking.
    I've seen the code. In places there was an 8 level indentation
    caused by if's switches and loops.

    There was also a ban on automatic testing. I got on a row, because
    I used a 3 line batch file (.BAT) to save on repetitive typing.

    Groetjes Albert
    --
    Temu exploits Christians: (Disclaimer, only 10 apostles)
    Last Supper Acrylic Suncatcher - 15Cm Round Stained Glass- Style Wall
    Art For Home, Office And Garden Decor - Perfect For Windows, Bars,
    And Gifts For Friends Family And Colleagues.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to [email protected] on Fri Jun 6 14:57:29 2025
    On 06/06/2025 13:45, [email protected] wrote:
    In article <101p8sd$phe5$[email protected]>,
    David Brown <[email protected]> wrote:
    <SNIP>
    I recall something of the opposite - a long time ago, we had to add a
    variety of "safety" features to a product to fulfil a customer's safety
    / reliability checklist, without regard to how realistic the failure
    scenarios were and without spending time and money on analysis. The
    result was, IMHO, lower reliability because it was more likely for the
    extra monitoring and checking hardware and software to fail than for the
    original functional stuff to fail. Many of these extra checks were in
    themselves impossible to test.

    I worked on the Dutch railway systems safety and control software.
    Once they added external control checking.
    I've seen the code. In places there was an 8 level indentation
    caused by if's switches and loops.


    I've occasionally seen that kind of thing from developers who come from
    the PLC world, having trained as automation engineers. In that world,
    it's not uncommon to have long changes of conditionals, which used to be implemented as chains of relays. If there are a dozen safety checks,
    each with an "OK" output, then you have them all in a line. If this is
    later translated into C code, if might then be translated into a series
    of indented if statements. You get similarly bad code design from
    people who are not programmers or trained in programming (at least, not
    that type of programming), but have somehow ended up with the task.

    There was also a ban on automatic testing. I got on a row, because
    I used a 3 line batch file (.BAT) to save on repetitive typing.


    That's a new one for me! I've certainly heard of management not wanting
    to spend time and money on doing much automatic testing, but never of
    people being actively against it like that.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From john larkin@21:1/5 to [email protected] on Fri Jun 6 06:40:44 2025
    On Fri, 06 Jun 2025 13:45:02 +0200, [email protected] wrote:

    In article <101p8sd$phe5$[email protected]>,
    David Brown <[email protected]> wrote:
    <SNIP>
    I recall something of the opposite - a long time ago, we had to add a >>variety of "safety" features to a product to fulfil a customer's safety
    / reliability checklist, without regard to how realistic the failure >>scenarios were and without spending time and money on analysis. The
    result was, IMHO, lower reliability because it was more likely for the >>extra monitoring and checking hardware and software to fail than for the >>original functional stuff to fail. Many of these extra checks were in >>themselves impossible to test.

    I worked on the Dutch railway systems safety and control software.
    Once they added external control checking.
    I've seen the code. In places there was an 8 level indentation
    caused by if's switches and loops.

    There was also a ban on automatic testing. I got on a row, because
    I used a 3 line batch file (.BAT) to save on repetitive typing.

    Groetjes Albert

    The advantage of a state machine is that it forces people to know the
    state of the system.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Carlos E.R.@21:1/5 to David Brown on Fri Jun 6 21:40:59 2025
    On 2025-06-06 14:57, David Brown wrote:
    On 06/06/2025 13:45, [email protected] wrote:
    In article <101p8sd$phe5$[email protected]>,
    David Brown  <[email protected]> wrote:
    <SNIP>
    I recall something of the opposite - a long time ago, we had to add a
    variety of "safety" features to a product to fulfil a customer's safety
    / reliability checklist, without regard to how realistic the failure
    scenarios were and without spending time and money on analysis.  The
    result was, IMHO, lower reliability because it was more likely for the
    extra monitoring and checking hardware and software to fail than for the >>> original functional stuff to fail.  Many of these extra checks were in
    themselves impossible to test.

    I worked on the Dutch railway systems safety and control software.
    Once they added external control checking.
    I've seen the code. In places there was an 8 level indentation
    caused by if's switches and loops.


    I've occasionally seen that kind of thing from developers who come from
    the PLC world, having trained as automation engineers.  In that world,
    it's not uncommon to have long changes of conditionals, which used to be implemented as chains of relays.

    I think it should be a chain of ANDs/ORs, not IFs.


    If there are a dozen safety checks,
    each with an "OK" output, then you have them all in a line.  If this is later translated into C code, if might then be translated into a series
    of indented if statements.  You get similarly bad code design from
    people who are not programmers or trained in programming (at least, not
    that type of programming), but have somehow ended up with the task.

    ...

    --
    Cheers, Carlos.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Carlos E.R. on Tue Jun 10 08:47:46 2025
    On 06/06/2025 21:40, Carlos E.R. wrote:
    On 2025-06-06 14:57, David Brown wrote:
    On 06/06/2025 13:45, [email protected] wrote:
    In article <101p8sd$phe5$[email protected]>,
    David Brown  <[email protected]> wrote:
    <SNIP>
    I recall something of the opposite - a long time ago, we had to add a
    variety of "safety" features to a product to fulfil a customer's safety >>>> / reliability checklist, without regard to how realistic the failure
    scenarios were and without spending time and money on analysis.  The
    result was, IMHO, lower reliability because it was more likely for the >>>> extra monitoring and checking hardware and software to fail than for
    the
    original functional stuff to fail.  Many of these extra checks were in >>>> themselves impossible to test.

    I worked on the Dutch railway systems safety and control software.
    Once they added external control checking.
    I've seen the code. In places there was an 8 level indentation
    caused by if's switches and loops.


    I've occasionally seen that kind of thing from developers who come
    from the PLC world, having trained as automation engineers.  In that
    world, it's not uncommon to have long changes of conditionals, which
    used to be implemented as chains of relays.

    I think it should be a chain of ANDs/ORs, not IFs.


    There are many ways to structure such a code requirement. And I agree
    that a chain of "ands" will often be better than a chain of "ifs".
    (Sometimes you want a chain of "ors" - but never a chain mixing "and"
    and "or".) Usually, however, it is best if the chains can be broken up
    into smaller logical parts - local flag variables or small functions -
    to avoid long chains of anything.


    If there are a dozen safety checks, each with an "OK" output, then you
    have them all in a line.  If this is later translated into C code, if
    might then be translated into a series of indented if statements.  You
    get similarly bad code design from people who are not programmers or
    trained in programming (at least, not that type of programming), but
    have somehow ended up with the task.

    ...


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)