The Real OS/2 Guy said:
The Real OS/2 Guy said:
struct foo
{
int dummy1;
int dummy2;
int last[1]
};
In application the above array is always allocated at runtime using
malloc.In this last member of the structer "int last[1]" is not
actually used as array with single element but when alloacting space
for struct foo extra memory is allocated and last is used as array
with more then one element.
No, it is NOT undefined behavior as Jack Klein says. But it is
implementation defined.
Yes, it is. Pointer addition beyond the end of the array is undefined.
Sou you says any action int an array allocated with malloc ends up in
undefined behavior.
Of course not, don't be daft! However did you get that idea?
You means that
int *p = malloc(4000),
stat *p1 = p + sizeof(stat) * 100;
stat *p2 = p1++;
is undefined behavior?
I don't know how you can construe what I wrote as meaning that all
pointer arithmetic is UB, but that's neither what I meant nor what I
wrote.
Where is undefined behavior here?
struct x {
size_t cb;
struct a *pa;
int val;
unsigned int flags;
char *sa[1000]; /* we need 3 to 999 chars here */
Whereas what you're getting is a thousand pointers to char - something
completely different.
};
struct y {
size_t cb;
struct a *pa;
int val;
unsigned int flags;
char s[1]; /* we have to compile ANSI C 89! */
};
struct x *p1 = malloc(sizeof(struct x) * 1000); /* UB? */
Of course not. Massive over-allocation, probably, but not UB.
struct y *p2 = malloc(sizeof(struct x) + strlen(data)); /* UB on what? */
No, this is not yet UB.
strcpy(y->s, data); /* UB? on what? */
Yes, this _is_ UB if more than one char is written - that is, if data
contains more than an empty string. You are writing to the array and
(most likely, since data is likely to contain something printable) write
beyond its boundary.
Since the behaviour of code which does this is not defined by the ISO C
Standard, it is, surprise, surprise, _undefined_.
Show one single ANSI C 89 compiler who will give undefined behavior
Compilers do not "give" undefined behaviour. The Standard _defines_
defined behaviour, and any _code_ which is not defined by the Standard
ipso facto invokes undefined behaviour.
Compilers have nothing to do with it, except insofar that they _must_
compile correct, not-undefined, code correctly, and _may_, but need not,
compile code invoking undefined behaviour into something which happens
to work.
I can see no UB in the code fragments above. But I see that any byte
addresse gets addressed well.
Non sequitur, AFAICT.
Tell me what is the difference between UB and and implementation
defined.
RTBS:
# [#1] implementation-defined behavior
# unspecified behavior where each implementation documents how
# the choice is made
# [#1] unspecified behavior
# behavior where this International Standard provides two or
# more possibilities and imposes no requirements on which is
# chosen in any instance
IOW, implementation-defined behaviour _must_ work, although it may work
differently using different implementations.
# [#1] undefined behavior
# behavior, upon use of a nonportable or erroneous program
# construct, of erroneous data, or of indeterminately valued
# objects, for which this International Standard imposes no
# requirements
# [#2] NOTE Possible undefined behavior ranges from ignoring
# the situation completely with unpredictable results, to
# behaving during translation or program execution in a
# documented manner characteristic of the environment (with or
# without the issuance of a diagnostic message), to
# terminating a translation or execution (with the issuance of
# a diagnostic message).
IOW, undefined behaviour _need not_ work, though it may do so if the
compiler writer feels like being helpful, or may appear to work but fail
every wednesday at four o'clock if he feels like being a bastard; in any
case, it _cannot_ be relied on.
Whenever you allocs memory in the size you needs - not a single byte
less - then you CAN'T get UB when you knows how to hanlde pointer
arithmetic.
Which, apparently, you do not.
Look, in a post elsewhere in this thread I pointed you at some examples
in the Standard that made this quite clear. Since you seem unable to
read printed matter or to download a file, I'll give one other example
myself, to point out exactly where the crux is:
struct foo {
int bar;
char ptr[10];
};
struct foo *afoo;
char *chptr;
afoo=malloc(sizeof *afoo + 100);
afoo->bar=10;
afoo->ptr[5]='a'; /* Legal; within the array. */
afoo->ptr[15]='b'; /* Illegal; outside the array. */
chptr=afoo;
chptr[sizeof *afoo + 50]='x';
/* Legal, since chptr points to the memory area, _not_ to the array
member. Also quite useless from ptr's POV, since we don't know
how much padding there is at the end of a struct foo. */
Richard