Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > why this program is not crashing

Reply
Thread Tools

why this program is not crashing

 
 
ghyott@yahoo.com
Guest
Posts: n/a
 
      02-11-2005
hello,
In my opinion the following code should crash when run with
*(argv+1)="1234567890" and *(argv+2)="1234567890" .

int main(int argc,char **argv)
{
char buf1[5];
char buf2[5];
char buf3[5];
strncpy(buf2,*(argv+1),sizeof(buf2));
strncpy(buf3,*(argv+2),sizeof(buf3));
sprintf(buf1,"%s",buf2);
return 0;
}

The last element of buf2 is not NULL.Therefore sprintf should copy
"1234512345"
to buf1 and which should result in segmentation fault.However,this is
not the case and the program is running normally.Can anybody please
pin-point my error.

Thanks

 
Reply With Quote
 
 
 
 
Ben Pfaff
Guest
Posts: n/a
 
      02-11-2005
http://www.velocityreviews.com/forums/(E-Mail Removed) writes:

> In my opinion the following code should crash when run with
> *(argv+1)="1234567890" and *(argv+2)="1234567890" .


You seem to be one of a class of newbies I spot here
occasionally, who think that *(a+b) is somehow different from
a[b]. That's not true, and the former just makes it look like
you don't know what you're doing.

> int main(int argc,char **argv)
> {
> char buf1[5];
> char buf2[5];
> char buf3[5];
> strncpy(buf2,*(argv+1),sizeof(buf2));
> strncpy(buf3,*(argv+2),sizeof(buf3));
> sprintf(buf1,"%s",buf2);
> return 0;
> }
>
> The last element of buf2 is not NULL.


Of course not--it's not a pointer. The proper terminology is
"null terminator", not NULL. The latter always refers to a
pointer.

> Therefore sprintf should copy "1234512345" to buf1 and which
> should result in segmentation fault.However,this is not the
> case and the program is running normally.Can anybody please
> pin-point my error.


There are two errors here. The first is your assumption that
buf2[] and buf3[] are stored contiguously, so that reading or
writing past the end of buf2[] will give you the beginning of
buf3[]. This is not guaranteed and many implementations will not
yield this behavior.

The second error is your assumption that accessing beyond the end
of buf3[] should produce a segmentation fault. The language does
not guarantee that. In fact, it does not make any guarantees at
all: the behavior is formally "undefined", meaning that anything
at all is allowed to happen.
--
"I should killfile you where you stand, worthless human." --Kaz
 
Reply With Quote
 
 
 
 
Richard Bos
Guest
Posts: n/a
 
      02-11-2005
(E-Mail Removed) wrote:

> In my opinion the following code should crash when run with
> *(argv+1)="1234567890" and *(argv+2)="1234567890" .


It could, but there's no guarantee.

> int main(int argc,char **argv)
> {
> char buf1[5];
> char buf2[5];
> char buf3[5];
> strncpy(buf2,*(argv+1),sizeof(buf2));
> strncpy(buf3,*(argv+2),sizeof(buf3));
> sprintf(buf1,"%s",buf2);
> return 0;
> }
>
> The last element of buf2 is not NULL.Therefore sprintf should copy
> "1234512345"


The last element of buf2 is never NULL, because NULL is a null pointer
constant and buf2 is an array of char. You mean that it's not null
(i.e., not a zero character), or not NUL (the ASCII character 0).

And no, it isn't; and therefore your program invokes undefined
behaviour, and may do whatever it pleases. This _could_ mean crashing;
it could also mean ignore whatever does not fit in the buffer; it could
also mean blot over whatever memory happens to lie beyond buf1 and
continue. The last option is particularly nasty if what happens to lie
beyond buf1 is a return address, or a totally unrelated variable which
you then use. In theory, invoking undefined behaviour could even result
in confusing the computer so badly that it writes your resignation
letter and emails it to your CEO.

BTW, even if you do assume (not necessarily correctly, but it's one of
the possibilities) that this particular kind of undefined behaviour
results in merrily trying to continue copying from beyond the end of the
source array, _and_ that your three arrays lie next to one another in
memory, I still don't see why that would try to copy "1234512345". You
have the same error with buf3 that you have with buf2; it would be more
likely that it would (try to) copy "1234512345Some random fluff that
happens to be on the stack beyond buf3, possibly including your return
address.".
Even then, the crash is hardly guaranteed, though. Undefined behaviour
is exactly that: undefined.

Richard
 
Reply With Quote
 
manoj1978@gmail.com
Guest
Posts: n/a
 
      02-11-2005

(E-Mail Removed) wrote:
> hello,
> In my opinion the following code should crash when run with
> *(argv+1)="1234567890" and *(argv+2)="1234567890" .


It crashed when i ran this with microsoft visual c 7
>
> int main(int argc,char **argv)
> {
> char buf1[5];
> char buf2[5];
> char buf3[5];
> strncpy(buf2,*(argv+1),sizeof(buf2));
> strncpy(buf3,*(argv+2),sizeof(buf3));
> sprintf(buf1,"%s",buf2);
> return 0;
> }
>
> The last element of buf2 is not NULL.Therefore sprintf should copy
> "1234512345"
> to buf1 and which should result in segmentation fault.However,this is
> not the case and the program is running normally.Can anybody please
> pin-point my error.
>
> Thanks

buf1,buf2 and buf3 are stored in stack,so incrementing pointer to buf2
goes towards buf1 not buf3.if they were global then it will be as you
say.

buf1,buf2 buf3 have padding to make them start in addresses divisible
by 4.so most possibly 3 bytes padding.one of them may be zero by chance
that may be why it didn't crash in your system.

 
Reply With Quote
 
manoj1978@gmail.com
Guest
Posts: n/a
 
      02-11-2005

(E-Mail Removed) wrote:
>
> buf1,buf2 buf3 have padding to make them start in addresses divisible
> by 4.

read the 4 as word size of processer. sorry about that.

 
Reply With Quote
 
Richard Bos
Guest
Posts: n/a
 
      02-11-2005
(E-Mail Removed) wrote:

> (E-Mail Removed) wrote:
> > int main(int argc,char **argv)
> > {
> > char buf1[5];
> > char buf2[5];
> > char buf3[5];
> > strncpy(buf2,*(argv+1),sizeof(buf2));
> > strncpy(buf3,*(argv+2),sizeof(buf3));
> > sprintf(buf1,"%s",buf2);
> > return 0;
> > }

> buf1,buf2 and buf3 are stored in stack,


Possibly, but even if so...

> so incrementing pointer to buf2 goes towards buf1 not buf3.


....there's no reason to assume that this is true in the general case. It
may be true for you, but that doesn't automatically make it true for the
OP or anyone else. Not all the world is a Microsoft boxlet.

> buf1,buf2 buf3 have padding to make them start in addresses divisible
> by 4.


There is no reason whatsoever to assume this.

Richard
 
Reply With Quote
 
manoj1978@gmail.com
Guest
Posts: n/a
 
      02-11-2005

Richard Bos wrote:
> (E-Mail Removed) wrote:
>
> > buf1,buf2 and buf3 are stored in stack,

>
> Possibly, but even if so...
>
> > so incrementing pointer to buf2 goes towards buf1 not buf3.

>
> ...there's no reason to assume that this is true in the general case.

It
> may be true for you, but that doesn't automatically make it true for

the
> OP or anyone else. Not all the world is a Microsoft boxlet.
>

If they are stored in stack,then the direction will be this.right? I am
not talking about the distance.

I made that comments after seeing gcc output.

~ > cat test.c
#include <stdio.h>

int main(void)
{
char buf1[5];
char buf2[5];
char buf3[5];
printf("%p %p %p\n",buf1,buf2,buf3);
return 0;
}
~ > gcc test.c
~ > ./a.out
ffbef958 ffbef950 ffbef948
~ > gcc -v
Reading specs from
/usr/local/lib/gcc-lib/sparc-sun-solaris2.8/2.95.3/specs
gcc version 2.95.3 20010315 (release)
~ >

 
Reply With Quote
 
Richard Bos
Guest
Posts: n/a
 
      02-11-2005
(E-Mail Removed) wrote:

> Richard Bos wrote:
> > (E-Mail Removed) wrote:
> >
> > > so incrementing pointer to buf2 goes towards buf1 not buf3.

> >
> > ...there's no reason to assume that this is true in the general case. It
> > may be true for you, but that doesn't automatically make it true for the
> > OP or anyone else. Not all the world is a Microsoft boxlet.
> >

> If they are stored in stack,then the direction will be this.right?


Wrong. You _do_ _not_ _know_ _this_. _Not_ all the world runs on your
kind of computer!

> I made that comments after seeing gcc output.


Never assume that _anything_ is required (or possibly even allowed) just
because Ganuck does it that way.

Richard
 
Reply With Quote
 
Jens.Toerring@physik.fu-berlin.de
Guest
Posts: n/a
 
      02-11-2005
(E-Mail Removed) wrote:

> Richard Bos wrote:
>> (E-Mail Removed) wrote:
>>
>> > buf1,buf2 and buf3 are stored in stack,

>>
>> Possibly, but even if so...
>>
>> > so incrementing pointer to buf2 goes towards buf1 not buf3.

>>
>> ...there's no reason to assume that this is true in the general case.

> It
>> may be true for you, but that doesn't automatically make it true for

> the
>> OP or anyone else. Not all the world is a Microsoft boxlet.
>>

> If they are stored in stack,then the direction will be this.right? I am
> not talking about the distance.


No. Already your first assumption that things are stored on a stack
is not necessary true - variables could also be in registers only or
there might be even machines not having a simple, linear stack. More-
over, things might not only depend on the direction the stack on your
machine grows (there are two alternatives, and both are used on diff-
erent architctures), but the compiler is in no way obliged to store
variables in a sequence resembling the the sequence the variables are
defined in the C code. It may, for example, recognize that, due to
alignment reasons, it would have to leave holes between the variables
and thus reorder them to avoid that as far as possible. So making any
assuptions about the relative positions of variables is plain wrong.
It may work in a certain way on your machine when you compile with a
certain set of options, but already changing the compiler options could
change things dramatically.
Regards, Jens
--
\ Jens Thoms Toerring ___ http://www.velocityreviews.com/forums/(E-Mail Removed)-berlin.de
\__________________________ http://www.toerring.de
 
Reply With Quote
 
infobahn
Guest
Posts: n/a
 
      02-11-2005
(E-Mail Removed) wrote:
>
> #include <stdio.h>
>
> int main(void)
> {
> char buf1[5];
> char buf2[5];
> char buf3[5];
> printf("%p %p %p\n",buf1,buf2,buf3);


printf, when faced with %p, expects to find a void * waiting for
it in its variable argument list. Since char * and void * have
the same size and representation, you *might* get away with it,
but in general it's wiser to cast non-void pointers when matching
them to %p, as follows:

printf("%p %p %p\n", (void *)buf1, (void *)buf2, (void *)buf3);
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
why this program is Crashing Pallav singh C++ 5 07-16-2009 08:30 AM
why why why why why Mr. SweatyFinger ASP .Net 4 12-21-2006 01:15 PM
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM
Why this program is crashing ??? code break C Programming 8 03-03-2006 07:56 PM
why this program is crashing James C Programming 6 04-18-2005 01:47 AM



Advertisments