pointer concepts

N

Newbie

Hi,

I'm a newbie. I need to clear my pointer concepts.

the code below gives segmentation fault when i use char* str;
int main()
{
char *str;
printf("Enter a string to reverse\n");
scanf("%s",&str);
strlen(str);
}

if I use char str[20] it runs fine.
int main()
{
char str[20];
printf("Enter a string to reverse\n");
scanf("%s",&str);
strlen(str);
}

Can you please explain why?

Thanks
 
N

Nelu

Newbie said:
Hi,

I'm a newbie. I need to clear my pointer concepts.

the code below gives segmentation fault when i use char* str;
int main() use: int main(void)
{
char *str;
printf("Enter a string to reverse\n");
scanf("%s",&str);
Here's the problem. str points to somewhere in memory
but you have no idea where and whether or not that area
belongs to you. You need to allocate memory (dynamically).
You can run into the problem again if you read more
characters than you allocated.
strlen(str); return something.
}

if I use char str[20] it runs fine.
Well, yes, because you str[20] is automatically
allocated and you tell it exactly how much memory
you want. To dynamically allocate memory you need
to use a pointer and allocate memory for it (malloc & co).
int main() int main(void)
{
char str[20];
printf("Enter a string to reverse\n");
scanf("%s",&str);
strlen(str); return something
}

Can you please explain why?
That's it.
 
V

Vladimir S. Oka

Nelu said:
Here's the problem. str points to somewhere in memory
but you have no idea where and whether or not that area
belongs to you. You need to allocate memory (dynamically).
You can run into the problem again if you read more
characters than you allocated.

Another problem, as big as not allocating any space for the string, is
that scanf("%s",...) requires `char*`, and you give it `char**`. You
(OP) used `&str` which yields the address of `str` variable, /not/ the
string it points to (even if one exists).

You don't seem to have high enough compiler warning setting, or you
ignored the one you got. My gcc complained...

The badness can be masked also if you just quickly test with the string
that will fit into the sizeof(char*) on your system (it would break
later, when you try to use now broken pointer).
strlen(str); return something.
}

if I use char str[20] it runs fine.
Well, yes, because you str[20] is automatically
allocated and you tell it exactly how much memory
you want. To dynamically allocate memory you need
to use a pointer and allocate memory for it (malloc & co).
int main() int main(void)
{
char str[20];
printf("Enter a string to reverse\n");
scanf("%s",&str);
strlen(str); return something
}

Can you please explain why?

Here, you have exactly the same problem as above. Use `str` and not
`&str` for scanf(). Don't get confused by other types. Revisit your
textbook sections on pointers and C strings.
That's it.

Indeed.
 
G

geshule

elu said:
You can run into the problem again if you read more
characters than you allocated.

I agree with you on that.
But the codes below works even if you input more than 10 characters?
Why?

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
char *str;
str = new char[10];
printf("Enter a string to reverse\n");
scanf("%s",str);
cout << strlen(str)<< endl;
system("pause");
return 0;
}
 
V

Vladimir S. Oka

elu said:
You can run into the problem again if you read more
characters than you allocated.

I agree with you on that.
But the codes below works even if you input more than 10 characters?
Why?

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
char *str;
str = new char[10];
printf("Enter a string to reverse\n");
scanf("%s",str);
cout << strlen(str)<< endl;
system("pause");
return 0;
}

I don't know, it's not C!
Please post C++ questions to comp.lang.c++

<OT>
I don't see why would it work for more characters than you allocate.
</OT>

--
BR, Vladimir

Goto, n.:
A programming tool that exists to allow structured programmers
to complain about unstructured programmers.
-- Ray Simard
 
N

Nelu

Vladimir said:
Another problem, as big as not allocating any space for the string, is
that scanf("%s",...) requires `char*`, and you give it `char**`. You
(OP) used `&str` which yields the address of `str` variable, /not/ the
string it points to (even if one exists).

You don't seem to have high enough compiler warning setting, or you
ignored the one you got. My gcc complained...

The badness can be masked also if you just quickly test with the string
that will fit into the sizeof(char*) on your system (it would break
later, when you try to use now broken pointer).
Right, I forgot to tell him that, and that if he uses an array
& will have the same address and wouldn't crash the program.
 
N

Nelu

elu said:
You can run into the problem again if you read more
characters than you allocated.

I agree with you on that.
But the codes below works even if you input more than 10 characters?
Why?

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
char *str;
str = new char[10];
printf("Enter a string to reverse\n");
scanf("%s",str);
cout << strlen(str)<< endl;
system("pause");
return 0;
}
This is not C. It is C++.
Also, some OSes (or kernel patches) try to avoid buffer overflows
and won't crash the program. However, don't trust them. It's wrong.
I had the same problem with someone who wrote a shell on RedHat a few
years ago and it was working just fine on his machine but crashed
instantly on my slackware. When I checked the code I was stunned.
He was using pointers without allocating any memory for them. His
kernel was patched to deal with buffer overflows so, even if his
program was way wrong it was not crashing. That's not normal behavior.
 
R

Richard Heathfield

Nelu said:
Right, I forgot to tell him that, and that if he uses an array
& will have the same address and wouldn't crash the program.

Quibble: given char arr[20], arr (in a value context) has type char *,
whereas &arr has type char (*)[20] - these are different and incompatible
types.

More importantly: what nobody seems to have mentioned is that scanf("%s" is
a remarkably dangerous construct, in that it offers no buffer protection
whatsoever.
 
V

Vladimir S. Oka

Nelu said:
Also, some OSes (or kernel patches) try to avoid buffer overflows
and won't crash the program. However, don't trust them. It's wrong.

This sounds absolutely /horrible/!

--
BR, Vladimir

Song Title of the Week:
"They're putting dimes in the hole in my head to see the change
in me."
 
N

Nelu

Richard said:
Quibble: given char arr[20], arr (in a value context) has type char *,
whereas &arr has type char (*)[20] - these are different and incompatible
types.
Yes. This was discussed on the list recently, I think.
More importantly: what nobody seems to have mentioned is that scanf("%s" is
a remarkably dangerous construct, in that it offers no buffer protection
whatsoever.
I think I told the OP about the problem if the buffer overflows.
 
R

Richard Heathfield

Nelu said:
Richard said:
Quibble: given char arr[20], arr (in a value context) has type char *,
whereas &arr has type char (*)[20] - these are different and incompatible
types.
Yes. This was discussed on the list recently, I think.
More importantly: what nobody seems to have mentioned is that scanf("%s"
is a remarkably dangerous construct, in that it offers no buffer
protection whatsoever.
I think I told the OP about the problem if the buffer overflows.

Have you a message ID? I count four articles from you in this thread, and
none of them mentions the specific danger of unadorned %s in a scanf format
string.
 
N

Nelu

Richard said:
Nelu said:
Richard said:
Quibble: given char arr[20], arr (in a value context) has type char *,
whereas &arr has type char (*)[20] - these are different and incompatible
types.
Yes. This was discussed on the list recently, I think.
More importantly: what nobody seems to have mentioned is that scanf("%s"
is a remarkably dangerous construct, in that it offers no buffer
protection whatsoever.
I think I told the OP about the problem if the buffer overflows.

Have you a message ID? I count four articles from you in this thread, and
none of them mentions the specific danger of unadorned %s in a scanf format
string.
In the first reply:
"You can run into the problem again if you read more
characters than you allocated."
 
R

Richard Heathfield

Nelu said:
In the first reply:
"You can run into the problem again if you read more
characters than you allocated."

Ah, thank you. I apologise for missing that.
 
N

Nelu

Richard said:
Nelu said:


Ah, thank you. I apologise for missing that.
No problem.
Now that I think of it I think I should have
written it a little better. I'm not a native English speaker
so, sometimes, I realize I could've done better a day after
saying something.
So this is actually a good thing, it makes me review things
and improve.

Thank you!
 
D

Default User

elu said:
You can run into the problem again if you read more
characters than you allocated.

I agree with you on that.
But the codes below works even if you input more than 10 characters?
Why?

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
char *str;
str = new char[10];
printf("Enter a string to reverse\n");
scanf("%s",str);
cout << strlen(str)<< endl;
system("pause");
return 0;
}

Ignoring the C++ part of it, which would be easy to correct, the reason
why it seems to work is bad luck. You're writing off the end of
allocated memory, possibly trashing some other allocated memory. This
is a major cause of, "How come this crashes when I do a free() on this
pointer?????"

Unfortunately, exceeding the bounds of dynamic memory isn't as likely
to provide a nice immediate crash, unlike some other forms of undefined
behavior.



Brian
 
E

Emmanuel Delahaye

Newbie a écrit :
I'm a newbie. I need to clear my pointer concepts.

A pointer is just another variable.
the code below gives segmentation fault when i use char* str;
int main()
{
char *str;
printf("Enter a string to reverse\n");
scanf("%s",&str);

Your compiler should complain about that.

This is wrong, because the type expected by scanf() with "%s" is char*.
The &str expression returns a value of type char ** (address of pointer
to char). The behaviour is indefined.
strlen(str);

str was not properly initilized. It's value is undefined. The behaviour
is undefined.

Bad, bad, bad...
}

if I use char str[20] it runs fine.
int main()
{
char str[20];
printf("Enter a string to reverse\n");
scanf("%s",&str);

Still wrong. Undefined behaviour.

You want the name of the array, because it is the address and type of
its first element (char *) as expected by "%s". Please read your C-book
again. As strange as it sounds, C-books give answers about C ...
strlen(str);
}

One more advidce. Don't follow your silly teacher on the scanf() way.
The way you are using it is wrong and dangerous. We recommend to use an
alternative to scanf() (not-a-beginner-function) as follow

Get a line with fgets()
Search and kill the '\n' with strchr()
If needed :

Convert with ssacnf() or strtol(), strtoul() or strtod() (other otions
in C99)
 
E

Emmanuel Delahaye

Newbie a écrit :
I'm a newbie. I need to clear my pointer concepts.

A pointer is just another variable.
the code below gives segmentation fault when i use char* str;
int main()
{
char *str;
printf("Enter a string to reverse\n");
scanf("%s",&str);

Your compiler should complain about that.

This is wrong, because the type expected by scanf() with "%s" is char*.
The &str expression returns a value of type char ** (address of pointer
to char). The behaviour is indefined.
strlen(str);

str was not properly initilized. It's value is undefined. The behaviour
is undefined.

Bad, bad, bad...
}

if I use char str[20] it runs fine.
int main()
{
char str[20];
printf("Enter a string to reverse\n");
scanf("%s",&str);

Still wrong. Undefined behaviour.

You want the name of the array, because it is the address and type of
its first element (char *) as expected by "%s". Please read your C-book
again. As strange as it sounds, C-books give answers about C ...
strlen(str);
}

One more advice. Don't follow your silly teacher on the scanf() way.
The way you are using it is wrong and dangerous. We recommend to use an
alternative to scanf() (not-a-beginner-function) as follow

Get a line with fgets()
Search and kill the '\n' with strchr()
If needed :

Convert with ssacnf() or strtol(), strtoul() or strtod() (other options
in C99)
 
R

Richard Heathfield

Emmanuel Delahaye said:
Newbie a écrit :

A pointer is just another variable.


Your compiler should complain about that.

Should, maybe. Must, no.

Convert with ssacnf() or strtol(), strtoul() or strtod() (other options
in C99)

ITYM sscanf().
 

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

No members online now.

Forum statistics

Threads
474,175
Messages
2,570,944
Members
47,491
Latest member
mohitk

Latest Threads

Top