Products > Programming

Should C language "undefined behaviour" cover crashing/hanging?

(1/26) > >>

HwAoRrDk:
I have been pondering this question for a few days.

After what started as an effort to write my own stripped-down, smaller printf() implementation after discovering I was nearly out of space on my MCU, I got nerd-sniped into also re-writing more efficient alternatives to my platform's C standard library 32-bit unsigned division and modulus software routines in assembly (they are used by ultoa(), which is used by my printf()). As part of testing my substitutes, I wanted to compare them to the behaviour of the standard library routines. So I wrote some test cases - some of which included dividing by zero. But to my surprise I discovered that the standard library implementation of modulus has a problem where the algorithm gets stuck in an infinite loop if the divisor is zero.

After reporting this to the maintainers, the opinion was given that it wasn't a problem, as "undefined behaviour" allows for that. I think that's a relatively cynical interpretation, and in my opinion "undefined behaviour" should - at least in this context - be that the result is undefined.

What say you lot in the peanut gallery? :)

ataradov:
It is allowed. "Result" in the context of a C spec is the state of the program, not an actual result returned by the function. So, getting stuck in a loop is a valid result as well.

Not only that, I've seen cases where GCC would replace the whole body of the function with a single instruction - UDF (architecturally undefined instruction on ARM) just because the function used an uninitialized pointer for a buffer and the rest of the code depended on that. So, the compiler eliminated all the code because as far as the spec goes, the result is the same. It could have itself replaced the whole function with a while (1);. It would have been just as valid.

In fact, I would call this behaviour desiderable in may cases. If the code gets stuck in the place where the issue is "detected", it makes it easier to debug. If the function just subtly returns the wrong result, you may have a lot of fun chasing it. Although in a more modern language, I would design in explicit checks and try to have as few undefined things as possible, ideally none. But this is not what C is, and it is to late to change.

MK14:

--- Quote from: HwAoRrDk on October 27, 2022, 03:26:44 pm ---opinion "undefined behaviour" should - at least in this context - be that the result is undefined.

What say you lot in the peanut gallery? :)

--- End quote ---

Nasal demons, might jump out, throw peanuts at you from the gallery, until you make a Riemann sphere.

Edit: Ideally, it should have produced a compiler error (perhaps in an ideal world), failing that a run time error (if possible, e.g. Divide by zero error).  But really, 'undefined behavior', can do just about anything, and probably more still.  So an infinite loop, is one example, of what it can do.

HwAoRrDk:
See, the thing is that I totally understand the arguments that "undefined behaviour" refers to the program state. That for example, what happens when accessing beyond the end of an array is also undefined behaviour - that it may corrupt other memory and thus potentially alter the state of the program.

But what would you say when given the following scenario? What if this code will not hang the program, but give a wrong result:


--- Code: ---a = 12345
b = 0;
c = a % b;

--- End code ---

And this code will hang the program in an endless loop:


--- Code: ---a = 12345
b = 0;
c = a % b;

--- End code ---

What do you mean, "there's no difference"?

Oh, I forgot to mention the first one is using unsigned int variables, and the other unsigned long. You see, on the platform in question, the former is performed with the CPU's native division instructions, whereas the latter is performed with a software routine that has the aforementioned behaviour. The two are inconsistent with each other for what is the same arithmetic operation. I think there is some merit in things failing in a predictable way when performing the same operation.

ataradov:

--- Quote from: HwAoRrDk on October 27, 2022, 05:09:45 pm ---I think there is some merit in things failing in a predictable way when performing the same operation.

--- End quote ---
Yes, there is, but this is not what C specification says. And compilers implement the specification. So, your complaint is to the standards people, not the compiler writers. And a lot of people have complaints to them, but they have their reasons.

All you can do is use a different language that does not have this behaviour.

If we are talking in abstract, I agree with you 100%. But when it comes to C, there is a well defined specification in place, it is fixed. You can implement "more robust" C, but it will likely break exiting software and there will be no market for it.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod