473,671 Members | 2,319 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Is this an error or undefined behaviour?

the following program, when compiled with gcc and '-std=c99', gcc says

test.c:6: error: jump into scope of identifier with
variably modified type

that is, it does not even compile.

lcc-win32, on the other hand, reports

Warning test.c: 7 unreachable code

the resulting program crashes at runtime, but I guess that can be
expected because x is probably uninitialized (UB?)
My question is, is the below program invalid or is undefined
behaviour invoked?

--------------------------------------------------
#include <stdio.h>
void func1(int n)
{
goto label;
int x[n];
label:
x[0] = 42;
printf("x[0] = %d\n", x[0]);
}

int main(void)
{
func1(5);

return 0;
}
--------------------------------------------------

Oct 28 '07 #1
12 5665
Franz Hose wrote:
....
My question is, is the below program invalid or is undefined
behaviour invoked?

--------------------------------------------------
#include <stdio.h>
void func1(int n)
{
goto label;
int x[n];
label:
x[0] = 42;
printf("x[0] = %d\n", x[0]);
}
Section 6.8.6.1p1: "A goto statement shall not jump from outside the
scope of an identifier having a variably modified type to inside the
scope of that identifier." This occurs within a constraint, so a
diagnostic message is mandatory. I would say that the standard doesn't
specify what happens if you do violate that constraint, so it is
undefined behavior "by the omission of any explicit definition of the
behavior".

However, deriving UB from omission is always a tricky argument - it's
possible that something said elsewhere in the standard provides the
definition that seems to have been omitted.
Oct 28 '07 #2
On Sun, 28 Oct 2007 02:08:04 +0000, James Kuyper wrote:
I would say that the standard doesn't
specify what happens if you do violate that constraint, so it is
undefined behavior "by the omission of any explicit definition of the
behavior".

However, deriving UB from omission is always a tricky argument - it's
possible that something said elsewhere in the standard provides the
definition that seems to have been omitted.
If a constraint is violated, and an implementation accepts the program
anyway, what happens when you run it is not within the scope of the
standard. Implementations are explicitly allowed to provide extensions
that don't alter the behaviour of strictly conforming programs.
Extensions that define the behaviour of constraint violations can't alter
the behaviour of strictly conforming programs, nor do they violate other
parts of the standard.
Oct 28 '07 #3
Harald van Dijk wrote:
On Sun, 28 Oct 2007 02:08:04 +0000, James Kuyper wrote:
>I would say that the standard doesn't
specify what happens if you do violate that constraint, so it is
undefined behavior "by the omission of any explicit definition of the
behavior".

However, deriving UB from omission is always a tricky argument - it's
possible that something said elsewhere in the standard provides the
definition that seems to have been omitted.

If a constraint is violated, and an implementation accepts the program
anyway, what happens when you run it is not within the scope of the
standard.

Implementations are explicitly allowed to provide extensions
that don't alter the behaviour of strictly conforming programs.
Extensions that define the behaviour of constraint violations can't alter
the behaviour of strictly conforming programs, nor do they violate other
parts of the standard.
The standard doesn't apply just to strictly conforming programs. If the
program is not strictly conforming because of undefined behavior, then
all bets are off. If it contains a syntax error or a constraint
violation, or exceeds an implementation limit, then an implementation is
allowed to reject it. However, an implementation which accepts code that
doesn't have undefined behavior is required to translate and execute it
in a way that conforms to all applicable requirements of the standard,
even if the program isn't strictly conforming.

Conforming implementations are allowed to extend the C language, but
only if the extension is enabled by a construct which renders the
behavior of the program undefined by the C standard.
Oct 28 '07 #4
James Kuyper wrote:
Harald van Dijk wrote:
On Sun, 28 Oct 2007 02:08:04 +0000, James Kuyper wrote:
I would say that the standard doesn't
specify what happens if you do violate that constraint, so it is
undefined behavior "by the omission of any explicit definition of the
behavior".

However, deriving UB from omission is always a tricky argument - it's
possible that something said elsewhere in the standard provides the
definition that seems to have been omitted.
If a constraint is violated, and an implementation accepts the program
anyway, what happens when you run it is not within the scope of the
standard.
>
Implementations are explicitly allowed to provide extensions
that don't alter the behaviour of strictly conforming programs.
Extensions that define the behaviour of constraint violations can't alter
the behaviour of strictly conforming programs, nor do they violate other
parts of the standard.

The standard doesn't apply just to strictly conforming programs.
Right, it also applies to "correct" programs (programs which contain
no syntax errors, constraint violations, or undefined behaviour, if I
haven't missed anything): 4p3 requires those to be accepted and
translated correctly.
If the
program is not strictly conforming because of undefined behavior, then
all bets are off. If it contains a syntax error or a constraint
violation, or exceeds an implementation limit, then an implementation is
allowed to reject it. However, an implementation which accepts code that
doesn't have undefined behavior is required to translate and execute it
in a way that conforms to all applicable requirements of the standard,
even if the program isn't strictly conforming.
In other words, printf("%d\n", INT_MAX); must print the value of
INT_MAX, and isn't allowed to print "I don't want to print INT_MAX",
even though the output is implementation-defined.

However, do you know where the standard says that

int main(void) {
return 1. % 2.;
}

must either be rejected, or return 0? This is not a correct program,
so if an implementation chooses to accept it, 4p3 doesn't require it
to behave as suggested by the description of the % operator, and I
don't see any other paragraph that does. And real-world
implementations already do define the behaviour for what standard C
calls constraint violations, as extensions.
Conforming implementations are allowed to extend the C language, but
only if the extension is enabled by a construct which renders the
behavior of the program undefined by the C standard.
Which I believe constraint violations do. Well, almost. "Undefined
behaviour" means there are absolutely no requirements, while a
constraint violation requires at least some sort of diagnostic,
regardless of whether the behaviour is defined.

--
Posted from Google because my ISP's news server is behind.

Oct 28 '07 #5
James Kuyper <ja*********@ve rizon.netwrites :
Keith Thompson wrote:
[...]
>A "constraint " is defined (C99 3.8) as a
restriction, either syntactic or semantic, by which the
exposition
of language elements is to be interpreted
If such a restriction is violated, how can the program be correctly
interpreted?

I think that there are relatively few constraints which, when
violated, still leave a clear definition of what the behavior should
be if an implementation chooses to accept them, but I think that there
are some.

I started searching for an example and came up with one that surprised
me. I'm looking at n1256.pdf, and found that it requires that the
operand of ++ be either real or a pointer. Why does it say 'real'
rather than 'arithmetic'? The ++ operator would pretty useless applied
to an imaginary type, but I don't see why there should be a problem
with complex types.
I think that applying ++ to a complex operand, though it could easily
be defined, just isn't useful enough to make it part of the language.
Similarly, "<<" and ">>" could be defined for floating-point and
complex types in terms of multiplication and division, but it's not
worth doing. In both cases, the primary usage would be in IOCCC
entries.
Whatever the reason for that constraint is, I believe that an
implementation which chooses to accept such code despite the fact that
a variable is complex, is required by 6.5.2.4p2 to implement it as
adding 1 to the value of that variable.
You may well be correct, but I'm going to disagree anyway. I think
the cases where the wording of a requirement applies even if a
constraint is violated are just coincidental. Stating the definition
of "++" so it explicitly doesn't apply to complex types would just
make it more verbose, to no real purpose.
The next example was more like what I expected: 6.5.3.2p1 - if an
implementation chooses to translate and execute code which attempts to
take the address of a variable declared with the 'register' keyword, I
believe it is still bound by 6.5.3.2p1, which would essentially mean
that it cannot place such a variable in a register. An implementation
is normally free to ignore a 'register' keyword - in this context, I
think that ignoring it becomes mandatory.
Quibble: any variable can be placed in a register (if it fits), at
least for part of its lifetime. It's a common optimization. But
that's beside the point.
I'm not absolutely committed to this point of view; if the committee
has actually ruled on this issue, rejecting this interpretation, I'll
accept that. However, if violating a constraint always leaves the
behavior undefined behavior (except for the mandatory issuance of a
diagnostic), I think it would be clearer to say so explicitly.
Agreed. I'm not sure whether this has been discussed in comp.std.c.
Unfortunately, "constraint violation" and "undefined behavior" aren't
great search terms. It won't hurt to ask again.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 29 '07 #6
Keith Thompson wrote:
James Kuyper <ja*********@ve rizon.netwrites :
....
>I think that there are relatively few constraints which, when
violated, still leave a clear definition of what the behavior should
be if an implementation chooses to accept them, but I think that there
are some.

I started searching for an example and came up with one that surprised
me. I'm looking at n1256.pdf, and found that it requires that the
operand of ++ be either real or a pointer. Why does it say 'real'
rather than 'arithmetic'? The ++ operator would pretty useless applied
to an imaginary type, but I don't see why there should be a problem
with complex types.

I think that applying ++ to a complex operand, though it could easily
be defined, just isn't useful enough to make it part of the language.
Similarly, "<<" and ">>" could be defined for floating-point and
complex types in terms of multiplication and division, but it's not
worth doing. In both cases, the primary usage would be in IOCCC
entries.
I think that it is rarely the case, and arguably never the case, that it
is appropriate to apply ++ to a floating point number. However, if there
are any cases where it is appropriate for a real floating point
variable, there should be corresponding cases where it is appropriate
for a complex floating point variable.

....
>I'm not absolutely committed to this point of view; if the committee
has actually ruled on this issue, rejecting this interpretation, I'll
accept that. However, if violating a constraint always leaves the
behavior undefined behavior (except for the mandatory issuance of a
diagnostic), I think it would be clearer to say so explicitly.

Agreed. I'm not sure whether this has been discussed in comp.std.c.
Unfortunately, "constraint violation" and "undefined behavior" aren't
great search terms. It won't hurt to ask again.
Oct 29 '07 #7
In article <onjVi.426$oy4. 161@trnddc08>,
James Kuyper <ja*********@ve rizon.netwrote:
>I think that it is rarely the case, and arguably never the case, that it
is appropriate to apply ++ to a floating point number.
Since there is a range of integer values that are guaranteed to be
exactly representable as doubles (and likewise for floats), it seems
reasonable to use doubles to store known-to-be-integer values if (for
example) you are going to pass them to library functions requiring
doubles. In that case, it also seems plausible to use the same idioms
for arithmetic that you would if they were ints.

I suppose the same could arise for complex numbers, but it's rather
less likely.

-- Richard
--
"Considerat ion shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Oct 29 '07 #8
James Kuyper wrote:
Franz Hose wrote:
...
>My question is, is the below program invalid or is undefined
behaviour invoked?

--------------------------------------------------
#include <stdio.h>
void func1(int n)
{
goto label;
int x[n];
label:
x[0] = 42;
printf("x[0] = %d\n", x[0]);
}

Section 6.8.6.1p1: "A goto statement shall not jump from outside the
scope of an identifier having a variably modified type to inside the
scope of that identifier." This occurs within a constraint, so a
diagnostic message is mandatory.
Well, lcc-win32 always prints a warning ("unreachabl e code"; is this
misleading?) even at the lowest warning level; so that part of the
standard should be satisfied.

[OT]
Looking at the generated code, internally,

int x[n];

is the roughly equivalent to

int *x = alloca(n * sizeof *x); /* allocate storage */
size_t hidden_sizeof_x = n*sizeof*x; /* what sizeof x evaluates to */

[/OT]

meaning, jumping over these leaves x unallocated as well as the
result of (sizeof x) indeterminate. When explicitly spelling out
the internal representation, I'd say it's U.B., but without that
knowledge, can the same still be said?

In a more complex example,

---------------------------------------
#include <stdio.h>

int blah = 1;

void func1(int n)
{
if(blah) goto label;
int x[n]; /* <== this is line 8 */
label:
printf("size = %lu\n", (unsigned long)sizeof x);
x[0] = 42;
printf("x[0] = %d\n", x[0]);
}

int main(void)
{
func1(100);

return 0;
}
---------------------------------------

at the highest warning level it says (is this misleading?)

Warning test.c: 8 x is assigned a value that is never used

but by default no warning is issued.
and the program output is

size = 2122776232
<CRASH!Unhandle d page fault on write access to [...]
Should I file a bug report?
(I really like lcc-win32 because of its small size)

I would say that the standard doesn't
specify what happens if you do violate that constraint, so it is
undefined behavior "by the omission of any explicit definition of the
behavior".

However, deriving UB from omission is always a tricky argument - it's
possible that something said elsewhere in the standard provides the
definition that seems to have been omitted.
Or is the observed U.B. still standard conform?

Oct 30 '07 #9
Franz Hose wrote:
James Kuyper wrote:
>Franz Hose wrote:
...
>>My question is, is the below program invalid or is undefined
behaviour invoked?

--------------------------------------------------
#include <stdio.h>
void func1(int n)
{
goto label;
int x[n];
label:
x[0] = 42;
printf("x[0] = %d\n", x[0]);
}
Section 6.8.6.1p1: "A goto statement shall not jump from outside the
scope of an identifier having a variably modified type to inside the
scope of that identifier." This occurs within a constraint, so a
diagnostic message is mandatory.

Well, lcc-win32 always prints a warning ("unreachabl e code"; is this
misleading?) even at the lowest warning level; so that part of the
That is not misleading; the code where x[n] is defined is unreachable,
and that is precisely the problem.
standard should be satisfied.

[OT]
Looking at the generated code, internally,

int x[n];

is the roughly equivalent to

int *x = alloca(n * sizeof *x); /* allocate storage */
size_t hidden_sizeof_x = n*sizeof*x; /* what sizeof x evaluates to */

[/OT]

meaning, jumping over these leaves x unallocated as well as the
result of (sizeof x) indeterminate. When explicitly spelling out
the internal representation, I'd say it's U.B., but without that
knowledge, can the same still be said?
I would say that the behavior is undefined, because the standard fails
to say what an expression involving a VLA means when the VLA hasn't
actually been created.
In a more complex example,

---------------------------------------
#include <stdio.h>

int blah = 1;

void func1(int n)
{
if(blah) goto label;
int x[n]; /* <== this is line 8 */
label:
printf("size = %lu\n", (unsigned long)sizeof x);
x[0] = 42;
printf("x[0] = %d\n", x[0]);
}

int main(void)
{
func1(100);

return 0;
}
---------------------------------------

at the highest warning level it says (is this misleading?)

Warning test.c: 8 x is assigned a value that is never used
That message makes sense in terms of the replacement code using alloca()
above. However, the programmer never sees that replacement code, and in
terms of the actual code, that message makes no sense, and makes it more
difficult to figure out what the real problem is.
but by default no warning is issued.
and the program output is

size = 2122776232
<CRASH!Unhandle d page fault on write access to [...]
Should I file a bug report?
My understanding is that the program's output is acceptable, but that
the diagnostic message needs some improvement.

....
>I would say that the standard doesn't
specify what happens if you do violate that constraint, so it is
undefined behavior "by the omission of any explicit definition of the
behavior".

However, deriving UB from omission is always a tricky argument - it's
possible that something said elsewhere in the standard provides the
definition that seems to have been omitted.

Or is the observed U.B. still standard conform?
That's a meaningless question. You can't observe UB, it isn't a
particular kind of behavior that, if it occurs, says "UB". UB can only
be deduced by comparison of a code sample with the standard. What UB
means, when it is correctly deduced, is that any behavior is permitted.

If my argument is correct, the behavior of this code is undefined, and
any behavior whatsoever is permitted to a conforming implementation of
C, including the <CRASHabove.

If my argument is incorrect, and the behavior is defined, then you need
to identify what the defined behavior is. In the unlikely case that the
defined behavior includes a crash, then the implementation is perfectly
conforming. :-)
Oct 30 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
2053
by: Chris Mantoulidis | last post by:
I see some really weird output from this program (compiled with GCC 3.3.2 under Linux). #include <iostream> using namespace std; int main() { char *s; s = "test1"; cout << "s = " << s << " and &s = " << &s << "\n";
8
4580
by: Scott J. McCaughrin | last post by:
The following program compiles fine but elicits this message from the linker: "undefined reference to VarArray::funct" and thus fails. It seems to behave as if the static data-member: VarArray::funct were an extern, but it is declared in the same file (q.v.). What is the remedy for this? =================
8
1814
by: Joona I Palaste | last post by:
We all know that this: void *p; if (p=malloc(1)) { free(p); p; } causes undefined behaviour if malloc() succeeds. But what about this?
25
3088
by: Nitin Bhardwaj | last post by:
Well, i'm a relatively new into C( strictly speaking : well i'm a student and have been doing & studying C programming for the last 4 years).....and also a regular reader of "comp.lang.c" I don't have a copy of ANSI C89 standard,therefore i had to post this question: What is the difference between "unspecified" behaviour & "undefined" behaviour of some C Code ??
12
1802
by: RoSsIaCrIiLoIA | last post by:
On Mon, 07 Feb 2005 21:28:30 GMT, Keith Thompson <kst-u@mib.org> wrote: >"Romeo Colacitti" <wwromeo@gmail.com> writes: >> Chris Torek wrote: >>> In article <4205BD5C.6DC8@mindspring.com> >>> pete <pfiland@mindspring.com> wrote: > >>> >If you have >>> > int array; >>> >then
69
5557
by: fieldfallow | last post by:
Hello all, Before stating my question, I should mention that I'm fairly new to C. Now, I attempted a small demo that prints out the values of C's numeric types, both uninitialised and after assigning them their maximum defined values. However, the output of printf() for the long double 'ld' and the pointer of type void 'v_p', after initialisation don't seem to be right. The compiler used was gcc (mingw) with '-Wall', '-std=c99' and
26
2178
by: Frederick Gotham | last post by:
I have a general idea of the different kinds of behaviour described by the C Standard, such as: (1) Well-defined behaviour: int a = 2, b = 3; int c = a + b; (Jist: The code will work perfectly.)
22
3256
by: Amali | last post by:
I'm newdie in c programming. this is my first project in programming. I have to write a program for a airline reservation. this is what i have done yet. but when it runs it shows the number of seats as 0 and the flight no. is also repeating. If any can tell why is this please help me. #include<stdio.h> #include<ctype.h> #include<conio.h>
3
1671
by: Scotty | last post by:
I'm a C++ novice and need help figuring out some odd behavior I've encountered. Here's the situation: I create a class and have its constructor store a random number in a private "number" variable. The class also has a "getNumber()" function that returns its stored number. A function in the program creates five objects of this class and five pointers to these objects, the latter of which are stored in a global array. When "getNumber()"...
0
8473
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8911
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8819
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8667
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7428
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5692
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4222
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
2808
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2048
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.