Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Why can I do this?

Reply
Thread Tools

Why can I do this?

 
 
Miguel
Guest
Posts: n/a
 
      10-11-2003
Why can I do this?? this is a cycle that when it reaches ? puts a
termination caracter \0, what I want to do is separate one String in
two

for(i=strlen(path);i>=0;i--){

if(!isspace(path[i])){
j++;
printf("nao e um espašo j->%d",j);
}
if (path[i]=='?'){
path[i]=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE
buf = (char*) malloc(j*sizeof(char));
strcpy(buf,&path[i+1]);
}
}
 
Reply With Quote
 
 
 
 
Floyd Davidson
Guest
Posts: n/a
 
      10-11-2003
http://www.velocityreviews.com/forums/(E-Mail Removed) (Miguel) wrote:
>Why can I do this?? this is a cycle that when it reaches ? puts a
>termination caracter \0, what I want to do is separate one String in
>two
>
> for(i=strlen(path);i>=0;i--){
>
> if(!isspace(path[i])){
> j++;
> printf("nao e um espašo j->%d",j);
> }
> if (path[i]=='?'){
> path[i]=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE


How is "path" defined???

Perhaps something like,

char *path = "/some/data/directory/";

If so, what you have is a pointer to a string literal, which is
allowed to be in write protected memory, and attempting to
modify it will cause a seg fault.

> buf = (char*) malloc(j*sizeof(char));


If you have properly included the stdlib.h header there is no
reason to use a cast. Likewise, sizeof(char) is guaranteed to
be equal to 1, so it is unnecessary. Your statement should be

buf = malloc(j);

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) (E-Mail Removed)
 
Reply With Quote
 
 
 
 
Mike Wahler
Guest
Posts: n/a
 
      10-11-2003

"Miguel" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) om...
> Why can I do this?? this is a cycle that when it reaches ? puts a
> termination caracter \0, what I want to do is separate one String in
> two
>
> for(i=strlen(path);i>=0;i--){
>
> if(!isspace(path[i])){
> j++;
> printf("nao e um espašo j->%d",j);
> }


Here, 'i' is equal to -1.

> if (path[i]=='?'){


'path[-1]' is probably outside the bounds of your array.
Evaluating it gives undefined behavior.
Dont Do That.


> path[i]=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE


Probably undefined behavior.

I say "probably" because you don't show how much
memory is actually represented by 'path'.

> buf = (char*) malloc(j*sizeof(char));


Don't cast the return value from 'malloc()'
sizeof(char) is one by definition.

buf = malloc(j);

> strcpy(buf,&path[i+1]);
> }
> }


-Mike


 
Reply With Quote
 
Don Porges
Guest
Posts: n/a
 
      10-12-2003

"Miguel" <(E-Mail Removed)> wrote in message news:(E-Mail Removed) om...
> Why can I do this?? this is a cycle that when it reaches ? puts a
> termination caracter \0, what I want to do is separate one String in
> two
>
> for(i=strlen(path);i>=0;i--){
>
> if(!isspace(path[i])){
> j++;
> printf("nao e um espašo j->%d",j);
> }
> if (path[i]=='?'){
> path[i]=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE
> buf = (char*) malloc(j*sizeof(char));
> strcpy(buf,&path[i+1]);
> }
> }


Among other things, you have

path[i]=='\0'; /* With 2 = characters */

where I'm sure you mean

path[i]='\0'; /* With 1 = character */



 
Reply With Quote
 
Floyd Davidson
Guest
Posts: n/a
 
      10-12-2003
"Mike Wahler" <(E-Mail Removed)> wrote:
>"Miguel" <(E-Mail Removed)> wrote in message
>news:(E-Mail Removed). com...
>> Why can I do this?? this is a cycle that when it reaches ? puts a
>> termination caracter \0, what I want to do is separate one String in
>> two
>>
>> for(i=strlen(path);i>=0;i--){
>>
>> if(!isspace(path[i])){
>> j++;
>> printf("nao e um espašo j->%d",j);
>> }

>
>Here, 'i' is equal to -1.


Can't happen. The value of i is between strlen(path) and 0,
otherwise the for loop would be exited. Perhaps this is a
good reason for more whitespace in the code, to make it more
readable...

for(i = strlen(path); i >= 0; i--){

>> if (path[i]=='?'){

>
>'path[-1]' is probably outside the bounds of your array.
>Evaluating it gives undefined behavior.
>Dont Do That.


See above.

>> path[i]=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE

>
>Probably undefined behavior.
>
>I say "probably" because you don't show how much
>memory is actually represented by 'path'.


The value of i cannot be less than 0 and cannot be greater than
the length of the string. Therefore we do know how much
memory is represented by 'path' and we know that path[i] is
within part of that memory.

>> buf = (char*) malloc(j*sizeof(char));

>
>Don't cast the return value from 'malloc()'
>sizeof(char) is one by definition.
>
>buf = malloc(j);
>
>> strcpy(buf,&path[i+1]);


Personally, I think that is too ugly. It is technically correct,
but I'd do it this way

strcpy(buf, path + i + 1);

>> }
>> }

>
>-Mike
>
>


--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) (E-Mail Removed)
 
Reply With Quote
 
Mike Wahler
Guest
Posts: n/a
 
      10-12-2003

"Floyd Davidson" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> "Mike Wahler" <(E-Mail Removed)> wrote:
> >"Miguel" <(E-Mail Removed)> wrote in message
> >news:(E-Mail Removed). com...
> >> Why can I do this?? this is a cycle that when it reaches ? puts a
> >> termination caracter \0, what I want to do is separate one String in
> >> two
> >>
> >> for(i=strlen(path);i>=0;i--){
> >>
> >> if(!isspace(path[i])){
> >> j++;
> >> printf("nao e um espašo j->%d",j);
> >> }

> >
> >Here, 'i' is equal to -1.

>
> Can't happen.


*Will* happen. The 'for' loop iterates while 'i'
is greater than or equal to zero. The only changes
made to 'i' are in the iteration expression of the
'for' loop (i--). So the only way for the loop to
terminate is when 'i' becomes equal to -1.


> The value of i is between strlen(path) and 0,


For a while, yes. Then when 'i' becomes zero,
the 'i--' makes it -1, the loop iterates one more
time, evalutes 'i >= 0' as false, and exits.
Thus i == -1 immediately after the loop.

> otherwise the for loop would be exited.


It *is* exited.

>Perhaps this is a
> good reason for more whitespace in the code, to make it more
> readable...


Nothing to do with whitespace.

>
> for(i = strlen(path); i >= 0; i--){
>
> >> if (path[i]=='?'){

> >
> >'path[-1]' is probably outside the bounds of your array.
> >Evaluating it gives undefined behavior.
> >Dont Do That.

>
> See above.


Read the code again.

>
> >> path[i]=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE

> >
> >Probably undefined behavior.
> >
> >I say "probably" because you don't show how much
> >memory is actually represented by 'path'.

>
> The value of i cannot be less than 0 and cannot be greater than
> the length of the string.


The code specifically gives 'i' a value of -1.
Look again.

>Therefore we do know how much
> memory is represented by 'path'


There is absolutely no way to determine the size of
the memory to which 'path' points from the code provided.

>and we know that path[i] is
> within part of that memory.


No we don't, not with the information provided.

Here's what we can see:

void foo(char *path)
{
for(i=strlen(path);i>=0;i--)
{
}
}

Here's a function from another part of a program
we don't see:

void f1()
{
char array[10] = "hello";
foo(array);
}

So now, only looking at 'foo', tell me how large block of
memory the pointer 'path' is pointing into.

Another possible function which calls 'foo()'
which we don't see:

void f2()
{
char array[10] = "hello world";
foo(array + 5);
}

Now, only looking at 'foo', tell me how large block of
memory the pointer 'path' is pointing into.

In the case of this call to 'foo()' the expression
'path[-1]' is OK.

But my point is, without seeing full context, we
*cannot* know the size of what 'path' points to.

That's why I said "probably" (guessing that the
beginning address of an array was passed, since
that's the most common thing to do). We don't
*know*.

-Mike



 
Reply With Quote
 
Floyd Davidson
Guest
Posts: n/a
 
      10-12-2003
"Mike Wahler" <(E-Mail Removed)> wrote:
>"Floyd Davidson" <(E-Mail Removed)> wrote:
>> "Mike Wahler" <(E-Mail Removed)> wrote:
>> >"Miguel" <(E-Mail Removed)> wrote:
>> >>
>> >> for(i=strlen(path);i>=0;i--){
>> >>
>> >> if(!isspace(path[i])){
>> >> j++;
>> >> printf("nao e um espašo j->%d",j);
>> >> }
>> >
>> >Here, 'i' is equal to -1.

>>
>> Can't happen.

>
>*Will* happen. The 'for' loop iterates while 'i'
>is greater than or equal to zero. The only changes
>made to 'i' are in the iteration expression of the
>'for' loop (i--). So the only way for the loop to
>terminate is when 'i' becomes equal to -1.


Exactly. The loop will terminate when i becomes -1.

Nothing inside the loop will ever be executed when
the value of i is -1.

>> The value of i is between strlen(path) and 0,

>
>For a while, yes. Then when 'i' becomes zero,
>the 'i--' makes it -1, the loop iterates one more
>time, evalutes 'i >= 0' as false, and exits.


See C99 6.8.5.3. The loop will *not* iterate one
more time. the "i--" is evaluated at the *end* of
each loop, not at the beginning of the loop. The
loop will *never* be executed with i set to -1.

>Thus i == -1 immediately after the loop.
>
>> otherwise the for loop would be exited.

>
>It *is* exited.


But the assignments to path were done *within* the
loop, not after it was exited.

Here is the entire snippet of code from the original post:

for(i=strlen(path);i>=0;i--){

if(!isspace(path[i])){
j++;
printf("nao e um espašo j->%d",j);
}
if (path[i]=='?'){
path[i]=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE
buf = (char*) malloc(j*sizeof(char));
strcpy(buf,&path[i+1]);
}
}

At exit, n will be equal to -1, but at no point within the
execution loop will it ever be less than 0.

>>Perhaps this is a
>> good reason for more whitespace in the code, to make it more
>> readable...

>
>Nothing to do with whitespace.


Well, your description of how a for loop works above is
incorrect, and/or it also seems you missed the beginning brace
of the compound statement making up the for loop too. The
assignment to path[n] is taking place within the loop, not after
the loop is terminated.

>> for(i = strlen(path); i >= 0; i--){
>>
>> >> if (path[i]=='?'){
>> >
>> >'path[-1]' is probably outside the bounds of your array.
>> >Evaluating it gives undefined behavior.
>> >Dont Do That.

>>
>> See above.

>
>Read the code again.


Indeed.

>>
>> >> path[i]=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE
>> >
>> >Probably undefined behavior.
>> >
>> >I say "probably" because you don't show how much
>> >memory is actually represented by 'path'.

>>
>> The value of i cannot be less than 0 and cannot be greater than
>> the length of the string.

>
>The code specifically gives 'i' a value of -1.
>Look again.


But not where that line of code is.

>>Therefore we do know how much
>> memory is represented by 'path'

>
>There is absolutely no way to determine the size of
>the memory to which 'path' points from the code provided.


We know how much there is which contains a valid string. There
could be more, but we don't care because we aren't writing outside
the boundaries of the string, only within it.

I think the OP's problem is simply that path actually is a
pointer, not an array, and points to a string literal in read
only memory.

>>and we know that path[i] is
>> within part of that memory.

>
>No we don't, not with the information provided.
>
>Here's what we can see:
>
>void foo(char *path)
>{
> for(i=strlen(path);i>=0;i--)
> {
> }
>}


Exactly. Now take that code and add a main() function and a
couple of function calls to meter it, and you'll see that

1) inside the for loop the value of i is never
less than 0, and

2) i always indexes a valid subscript within path
(assuming that path points to a valid string).

Here, try it:

#include <stdio.h>
#include <string.h>
void foo(char *path) {
int i;
for(i = strlen(path); i >= 0; --i) {
printf("At i == %d; path is [%s]\n", i, &path[i]);
}
}
int main(int argc, char *argv[]) {
if (argc > 1) foo(argv[1]);
return 0;
}

Here is what it prints out:

>./foo bar

At i == 3; path is []
At i == 2; path is [r]
At i == 1; path is [ar]
At i == 0; path is [bar]

You cannot find a valid string for which i will ever be -1.

>Here's a function from another part of a program
>we don't see:
>
>void f1()
>{
> char array[10] = "hello";
> foo(array);
>}
>
>So now, only looking at 'foo', tell me how large block of
>memory the pointer 'path' is pointing into.
>
>Another possible function which calls 'foo()'
>which we don't see:
>
>void f2()
>{
> char array[10] = "hello world";
> foo(array + 5);
>}
>
>Now, only looking at 'foo', tell me how large block of
>memory the pointer 'path' is pointing into.
>
>In the case of this call to 'foo()' the expression
>'path[-1]' is OK.
>
>But my point is, without seeing full context, we
>*cannot* know the size of what 'path' points to.


We only need to know how big the string contained in
the array is. All of the above is both wonderful and
useless to the OP's program.

>That's why I said "probably" (guessing that the
>beginning address of an array was passed, since
>that's the most common thing to do). We don't
>*know*.
>
>-Mike



--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) (E-Mail Removed)
 
Reply With Quote
 
Irrwahn Grausewitz
Guest
Posts: n/a
 
      10-12-2003
(E-Mail Removed) (Miguel) wrote:

>Why can I do this?? this is a cycle that when it reaches ? puts a
>termination caracter \0, what I want to do is separate one String in
>two
>


First off:
- How is path declared?
- You failed to initialize j (at least in the code you posted).

> for(i=strlen(path);i>=0;i--){
>
> if(!isspace(path[i])){
> j++;


Next, you increment j only if path[i] is not a white-space (see below
for the consequences).

> printf("nao e um espašo j->%d",j);
> }
> if (path[i]=='?'){
> path[i]=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE


No SEGFAULT here, but warning: statement with no effect.
You most probably want:

path[i] = '\0';

instead.

> buf = (char*) malloc(j*sizeof(char));


Even if you change this (strongly suggested) to:

buf = malloc( j );

your code most probably SEGFAULTs in strcpy, because if white-spaces
occurred (see above), you fail to allocate enough space for buf to
hold the string you copy!

> strcpy(buf,&path[i+1]);
> }
> }


And, of course, you have to make sure that path is not a pointer to a
string literal (which [the literal] you aren't allowed to change).

I deliberately changed your code and completed it to form a compilable
example; here it is:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define PATHLEN 42

int main( void )
{
int i;
int j;
char *buf = NULL;
char path[PATHLEN] = "abcd efg/xyz ? qwert/h jk";

printf( "Before: %s\n", path );

j = 0;
for( i = strlen(path); i >= 0; i-- )
{
j++;
if ( path[i] == '?' )
{
path[i] = '\0';
buf = malloc( j );
strcpy( buf, path + i + 1 );
}
}

printf( "After: %s\n %s\n", path, buf );

free( buf );
return 0;
}

However, note that this code still produces a memory leak if path
contains more than one '?'!!!

Regards
--
Irrwahn
((E-Mail Removed))
 
Reply With Quote
 
Irrwahn Grausewitz
Guest
Posts: n/a
 
      10-12-2003
"Mike Wahler" <(E-Mail Removed)> wrote:
>
>"Miguel" <(E-Mail Removed)> wrote in message
>news:(E-Mail Removed). com...
>> Why can I do this?? this is a cycle that when it reaches ? puts a
>> termination caracter \0, what I want to do is separate one String in
>> two
>>
>> for(i=strlen(path);i>=0;i--){
>>
>> if(!isspace(path[i])){
>> j++;
>> printf("nao e um espašo j->%d",j);
>> }

>
>Here, 'i' is equal to -1.


Apparently, no. But admittedly I misread the code the first time I came
across, most probably the same way you did, it seems to me; so all your
statements about UB below are right claims based on a wrong premiss.
Things happen.

[OT]
This is just another good example for why I dislike the "Indian (H)ill"
bracing style. No offense or style war intended, just my personal
opinion.
[/OT]

>
>> if (path[i]=='?'){

>
>'path[-1]' is probably outside the bounds of your array.
>Evaluating it gives undefined behavior.
>Dont Do That.


See above.

>
>> path[i]=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE

>
>Probably undefined behavior.


See above.

>I say "probably" because you don't show how much
>memory is actually represented by 'path'.
>
>> buf = (char*) malloc(j*sizeof(char));

>
>Don't cast the return value from 'malloc()'
>sizeof(char) is one by definition.
>
>buf = malloc(j);


Right, that's much better.

>
>> strcpy(buf,&path[i+1]);
>> }
>> }

>


Regards
--
Irrwahn
((E-Mail Removed))
 
Reply With Quote
 
Irrwahn Grausewitz
Guest
Posts: n/a
 
      10-12-2003
"Mike Wahler" <(E-Mail Removed)> wrote:

>
>"Floyd Davidson" <(E-Mail Removed)> wrote in message
>news:(E-Mail Removed)...
>> "Mike Wahler" <(E-Mail Removed)> wrote:
>> >"Miguel" <(E-Mail Removed)> wrote in message
>> >news:(E-Mail Removed). com...

<SNIP>
>> >> for(i=strlen(path);i>=0;i--){
>> >>
>> >> if(!isspace(path[i])){
>> >> j++;
>> >> printf("nao e um espašo j->%d",j);
>> >> }
>> >
>> >Here, 'i' is equal to -1.

>>
>> Can't happen.

>
>*Will* happen.


*Cannot* happen; you misread (I did too in the first place),
see my other replies.

<SNIP>

Regards
--
Irrwahn
((E-Mail Removed))
 
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 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
Cisco 2611 and Cisco 1721 : Why , why , why ????? sam@nospam.org Cisco 10 05-01-2005 08:49 AM
Can someone tell me why I can't delete this file? and why it blue screens WinXP Pro on delete? zZz Computer Support 1 01-12-2005 02:37 AM
Why Why Why You HAVE NO IDEA MCSE 31 04-24-2004 06:40 PM



Advertisments