Why can I do this?

M

Miguel

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)){
j++;
printf("nao e um espaço j->%d",j);
}
if (path=='?'){
path=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE
buf = (char*) malloc(j*sizeof(char));
strcpy(buf,&path[i+1]);
}
}
 
F

Floyd Davidson

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)){
j++;
printf("nao e um espaço j->%d",j);
}
if (path=='?'){
path=='\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);
 
M

Mike Wahler

Miguel said:
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)){
j++;
printf("nao e um espaço j->%d",j);
}


Here, 'i' is equal to -1.
if (path=='?'){


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

path=='\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
 
D

Don Porges

Miguel said:
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)){
j++;
printf("nao e um espaço j->%d",j);
}
if (path=='?'){
path=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE
buf = (char*) malloc(j*sizeof(char));
strcpy(buf,&path[i+1]);
}
}


Among other things, you have

path=='\0'; /* With 2 = characters */

where I'm sure you mean

path='\0'; /* With 1 = character */
 
F

Floyd Davidson

Mike Wahler said:
Miguel said:
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)){
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=='?'){


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


See above.
path=='\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 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);
 
M

Mike Wahler

Floyd Davidson said:
Mike Wahler said:
Miguel said:
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)){
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=='?'){


'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=='\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 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
 
F

Floyd Davidson

Mike Wahler said:
Floyd Davidson said:
Mike Wahler said:
for(i=strlen(path);i>=0;i--){

if(!isspace(path)){
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.
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.


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)){
j++;
printf("nao e um espaço j->%d",j);
}
if (path=='?'){
path=='\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.
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=='?'){

'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=='\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.
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 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);
}
}
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.
 
I

Irrwahn Grausewitz

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)){
j++;


Next, you increment j only if path is not a white-space (see below
for the consequences).
printf("nao e um espaço j->%d",j);
}
if (path=='?'){
path=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE


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

path = '\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 == '?' )
{
path = '\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
 
I

Irrwahn Grausewitz

Mike Wahler said:
Miguel said:
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)){
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=='?'){


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


See above.
path=='\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'.


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
 
M

Mike Wahler

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

My wife told me it was not a good idea to stay
awake for three days. :)

I commited a similar faux pas with a 'dynterpret_cast'
in clc++ :)

Apologies for my idiotic post, Floyd.

G'night all!

-Mike
 
F

Floyd Davidson

Mike Wahler said:
My wife told me it was not a good idea to stay
awake for three days. :)

I commited a similar faux pas with a 'dynterpret_cast'
in clc++ :)

Apologies for my idiotic post, Floyd.

G'night all!

-Mike

Everybody does that. The measure of a person is whether they get
overly snotty in the process (you didn't) and then how they react
when they realize they goofed.

You measure up pretty well.
 
P

Peter Shaggy Haywood

Groovy hepcat Miguel was jivin' on 11 Oct 2003 14:07:12 -0700 in
comp.lang.c.
Why can I do this?'s a cool scene! Dig it!
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)){
j++;
printf("nao e um espaço j->%d",j);
}
if (path=='?'){
path=='\0'; --------->>>>>>>>>>>SEGMENTACION FAULT HERE

^^
You're comparing here, instead of assigning. If this isn't your real
code, then why isn't it? Cut and paste; do not retype.
buf = (char*) malloc(j*sizeof(char));

You are leaking memory if this line is executed more than once.
Nowhere do you free this memory, but just overwrite the previous value
of buf, which may be the address of the last block of dynamically
allocated memory.
strcpy(buf,&path[i+1]);
}
}

Since you posted only a small portion of code, instead of a whole
program, we cannot compile it to see what might be wrong. We're left
to guess what might be the cause of the problem.
Post a *complete* program that demonstrates the problem. By
"complete" I don't mean a 50000 line program that does everything. I
mean a small program that just tries to do one thing, but one that is
complete enough to compile. Cut down your full program to the smallest
complete program that still demonstrates the problem. (And do try to
compile and run it to make sure it *does* actually demonstrate the
problem.) Cut and paste this code into your post; do not retype it.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top