why this crash?

L

linq936

Hi,
It could be a very simple problem, but i can not see it...

Here is the code:

char* lower(char* str){
char* p = str;
while ( *str ) {
*str = tolower(*str); <=====crash!
str++;
}
return p;
}

DO you see why?
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Hi,
It could be a very simple problem, but i can not see it...

Here is the code:

char* lower(char* str){
char* p = str;
while ( *str ) {
*str = tolower(*str); <=====crash!
str++;
}
return p;
}

After removing the "<=====crash!":

test.c: In function ‘lower’:
test.c:4: warning: implicit declaration of function ‘tolower’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/../../../../lib64/crt1.o: In function
`_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status

Please, when possible, post complete compilable programs.
DO you see why?

You have not posted enough code to make this clear. One likely possibility
is explained in the FAQ at <http://c-faq.com/decl/strlitinit.html>, but
there are other possibilities. If this is what happened, then the problem
is not in the code that you posted, but in how you call the lower function.
If you had posted a complete compilable program, it would have been
possible to be sure if this is what happened.
 
K

Keith Thompson

It could be a very simple problem, but i can not see it...

Here is the code:

char* lower(char* str){
char* p = str;
while ( *str ) {
*str = tolower(*str); <=====crash!
str++;
}
return p;
}

DO you see why?

No, because you didn't post the entire program, so we can't see where
the actual error is.

But I note that if you call your lower() function with a string
literal as the argument, a crash is very likely.

You should also be careful with the argument you pass to tolower(). A
negative value other than EOF causes undefined behavior; if plain char
is signed on your system, that could also cause a crash.
 
S

sid

Hi,
It could be a very simple problem, but i can not see it...

Here is the code:

char* lower(char* str){
char* p = str;
while ( *str ) {
*str = tolower(*str); <=====crash!
str++;
}
return p;

}

DO you see why?

I am not sure but I think the argument is supposed to be passed like
char *str and not char* str. If I am wrong kindly correct me and also
please tell me the difference between the two.
Thank you
 
M

Martin Ambuhl

sid said:
I am not sure but I think the argument is supposed to be passed like
char *str and not char* str. If I am wrong kindly correct me and also
please tell me the difference between the two.

a) You are wrong
b) There is no difference
 
R

Robert Gamble

I am not sure but I think the argument is supposed to be passed like
char *str and not char* str.

You are incorrect.
If I am wrong kindly correct me and also
please tell me the difference between the two.

There is no difference in this context, it is a matter of style.

Robert Gamble
 
J

J. J. Farrell

I am not sure but I think the argument is supposed to be passed like
char *str and not char* str. If I am wrong kindly correct me

Consider yourself kindly corrected.
and also
please tell me the difference between the two.

The characters '*' and ' ' are transposed - that's the only difference.
 
D

Default User

Hi,
It could be a very simple problem, but i can not see it...

Here is the code:

char* lower(char* str){
char* p = str;
while ( *str ) {
*str = tolower(*str); <=====crash!
str++;
}
return p;
}

DO you see why?

No. You only showed us part of the code. Post a complete, minimal
program that demonstrates the problem.

I'll bet you passed it a string literal.



Brian
 
A

Army1987

Hi,
It could be a very simple problem, but i can not see it...

Here is the code:

char* lower(char* str){
char* p = str;
while ( *str ) {
*str = tolower(*str); <=====crash!
Are plain chars signed on your system?
Try *str = (char)tolower((unsigned char)*str);
 
A

Army1987

sid said:
I am not sure but I think the argument is supposed to be passed like
char *str and not char* str. If I am wrong kindly correct me and also
please tell me the difference between the two.
None. You could also use char*str. Whitespace isn't significant in C.
 
T

tguclu

No. You only showed us part of the code. Post a complete, minimal
program that demonstrates the problem.

I'll bet you passed it a string literal.

Brian- Hide quoted text -

- Show quoted text -

Hi,
Why passing string literal crashes the program?
I've completed and made some tryings on his code.

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


char* lower(char* str)
{
char* p = str;
while ( *str )
{
*str = tolower(*str); //<=====crash!
str++;
}
return p;
}


int main()
{
char *dd = (char *)malloc(sizeof(char)*2);
strcpy(dd,"DD");
puts(lower(dd)); //crashes, if changed with puts(lower("DD"));
return 0;
}

Above code works , but if i call the lower func. with string literal
as an argument it crashes.
After crash i changed the declaration of func. lower as char*
lower(const char* str) but i got the compile error "assignment of read-
only location" at line labeled as //<=====crash!

What can be done on this fun. to work with string literals rather than
passing them to pointers ?

Thanks..
 
C

Chris Dollin

Why passing string literal crashes the program?

You're not allowed to update a string literal. If you try, the implementation
can do /anything it likes/. In this case, it was helpful, and blew your
program up.

(fx:snip)
char* lower(char* str)
int main()
{
char *dd = (char *)malloc(sizeof(char)*2);
strcpy(dd,"DD");

Oops. You've tried to copy three characters ('D', 'D', /and/ '\0')
into space big enough for only two. All Bets Are Now Off.
puts(lower(dd)); //crashes, if changed with puts(lower("DD"));
After crash i changed the declaration of func. lower as char*
lower(const char* str) but i got the compile error "assignment of read-
only location" at line labeled as //<=====crash!

Well, of course.
What can be done on this fun. to work with string literals rather than
passing them to pointers ?

Nothing. You're not allowed to update string literals.
 
C

CBFalconer

tguclu said:
.... snip ...

int main()
{
char *dd = (char *)malloc(sizeof(char)*2);
strcpy(dd,"DD");
puts(lower(dd)); //crashes, if changed with puts(lower("DD"));
return 0;
}

Above code works , but if i call the lower func. with string
literal as an argument it crashes.

Because string literals are not modifiable. Neither are they
marked as const, due to historical reasons. You can mark them as
const if you like. They may be stored in read-only memory, shared
with other declarations, etc.
 
K

Keith Thompson

tguclu said:
Why passing string literal crashes the program?
I've completed and made some tryings on his code.

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


char* lower(char* str)
{
char* p = str;
while ( *str )
{
*str = tolower(*str); //<=====crash!
str++;
}
return p;
}

A stylistic note: you copy the original value of the parameter 'str'
to 'p', then modify 'str' in your loop. There's nothing wrong with
that, but I'd probably do it the other way around: maintain 'str' with
its original value, and modify the copy. It's not a big deal, I just
find it a bit clearer that way.
int main()

That's ok, but it's better to be more explicit:

int main(void)
{
char *dd = (char *)malloc(sizeof(char)*2);

Don't cast the result of malloc. See questions 7.7, 7.7b, and 7.7c in
the FAQ, <http://www.c-faq.com/>. In fact, *most* casts are
unnecessary.

sizeof(char) is 1 by definition. If you know you're always going to
be allocating characters, you can write the above as:

char *dd = malloc(2);

If there's some possibility that you might change dd to some other
pointer type in the future, the recommended idiom is:

char *dd = malloc(2 * sizeof *dd);

(By applying sizeof to *dd, you automatically get the right type even
if you change the declaration).

malloc can fail; it indicates failure by returning a null pointer
value. Always check for this. (It's probably ok to leave out the
check in a small sample program like this one, but in that case add a
comment saying that you've left it out.)
strcpy(dd,"DD");

As somebody else pointed out, this copies 3 bytes ('D', 'D', '\0')
into an array of 2 elements (assuming malloc succeeded).

If I wanted to make sure the code is flexible in the face of future
changes, I might do this:

#define THE_STRING "DD"
char *dd = malloc(sizeof THE_STRING);
/* check whether malloc failed */
strcpy(dd, THE_STRING);

or perhaps:

#define THE_STRING "DD"
char *dd = malloc(strlen(THE_STRING) + 1);
/* check whether malloc failed */
strcpy(dd, THE_STRING);

I'm not suggesting that this kind of thing is necessary for a small
sample program like this one, but it's something to keep in mind for
future programs.
puts(lower(dd)); //crashes, if changed with puts(lower("DD"));
return 0;
}
[...]
 
L

linq936

No. You only showed us part of the code. Post a complete, minimal
program that demonstrates the problem.

I'll bet you passed it a string literal.

Brian

Your bet wins.
 

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,780
Messages
2,569,608
Members
45,252
Latest member
MeredithPl

Latest Threads

Top