Sujet : Re: Two questions on arrays with size defined by variables
De : david.brown (at) *nospam* hesbynett.no (David Brown)
Groupes : comp.lang.cDate : 10. Feb 2025, 11:39:40
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <vocl1c$157k1$2@dont-email.me>
References : 1 2 3 4 5 6 7 8 9 10
User-Agent : Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0
On 10/02/2025 03:01, Janis Papanagnou wrote:
On 09.02.2025 21:55, James Kuyper wrote:
On 2/9/25 12:53, Janis Papanagnou wrote:
On 09.02.2025 18:46, Janis Papanagnou wrote:
[...] my test-wise - deliberately
wrong! - assignment to 'a[99]' produced also no compiler complaints,
>
BTW, it produced also no core dump or any other runtime error.
(But it is obviously severely wrong code anyway.)
>
Accessing an array beyond it's bounds has undefined behavior, whether or
not it is a VLA. "undefined behavior" means that the C standard imposes
no requirements on the behavior. In particular, it does not require a
diagnostic message, nor a core dump, nor any other kind of runtime error.
Yes. (There's reasons why I prefer programming languages with checks.)
[...]
In this particular case. however, it would be trivial to detect the
violation, but none of the compilers I've tested do so.
Yes, because it's a special case with a constant defined. But the
value may come from "outside", undetectable by the compiler and only
detectable during runtime if there's additional information maintained
(stored and checked).
When such code is accepted by an implementation, what is most likely to
happen is that the compiler will generate code that creates an array
containing "foobar", and which attempts to write a pointer to the first
element of that array to the location where a[99] should be, if a had at
least 100 elements. Depending upon what that piece of memory is being
used for, the results could be catastrophic, or completely innocuous, or
somewhere in-between.
Yes. That matches exactly my fears or expectations here [with "C"].
Janis
Let's assume your full code is :
int main() {
int n = 5;
char * arr[n];
arr[99] = "foobar";
}
In C, that means exactly the same as a do-nothing program:
int main() { }
There is no observable behaviour. So an optimising compiler (like gcc, if you have enabled optimisation) will give a program that simply returns 0.
If optimisation is not enabled, or a weak compiler is used, the array will be put on the stack and your assignment will write to a part of the stack that exists in memory. It /might/ stomp over something important, but there's a fair chance that - by luck - nothing bad happens.
The C language does not have much in the way of checks other than for syntax, grammar and constraints. But C /implementations/ do far better, as long as you enable them.
When you are checking code like this, I recommend you get in the habit of using <
https://godbolt.org> for convenience, as it makes it easy to check snippets with the newest compiler versions. And use command-line flags such as :
-std=c99 -Wpedantic -Wall -Wextra -O2
The "-Wpedantic" makes sure that all standards-required diagnostics are produced (to the best of the compiler's abilities). "-Wall" should always be used as a basis to give useful warnings. "-Wextra" is more debatable - it warns on things that some people feel is good coding practice, other people feel is poor coding practice. But I think it is very useful for this kind of thing, even if you don't use it in your main development. And it is a good idea to enable optimisation - it makes warnings better, and it gives you a better idea of what your code /really/ means.
So with this example code, you'd see the virtually empty generated assembly, and a warning that "arr" is set but never used. (I am disappointed that neither gcc nor clang can spot the clearly out-of-bounds access.)
Sometimes gcc will give the best static error checking, sometimes clang - use both tools.
The next step is to use run-time checkers. Compile the code with the flag "-fsanitize=undefined" and you will get a run-time check and run-time error on the array bounds violation. (You can do this from within godbolt.org).
C (and C++) have a vast range of checks available to developers - you just have to know how to use them.