Click to See Complete Forum and Search --> : C++ - Beginner Question
A very beginnery C++ question. Why does this code segfault when it gets to return 0 (or maybe the line before it, I don't know):
#include "iostream"
using namespace std;
int main()
{
char Ch;
char * pCh;
cout << "What is your name?" << endl;
cin >> pCh;
cout << "Hello, " << pCh << "!" << endl;
return 0;
}
Also, if I remove the "char Ch;" line, it segfaults before saying "Hello...!" Why would that make a difference? Should I somehow be pointing pCh at Ch? Basically, I'm just trying to understand some syntaxes and stuff :-)
pezplaya
06-09-2005, 06:21 PM
Well with this example you don't really need to use pointers. I figure you are just trying certain things to see how everything works together.
Your include statement should have < > instead of " ".
#include <iostream>. You use " " when you have a header file you created and want to include it.
Next, in your program you declared char Ch; but you never used it in the program. pCh is then a pointer to nothing really.
Arrays are always passed by reference, therefore you can assign a pointer to an array. Then everything should work out. I made the size of the character array 20... that should be sufficient for most names. You can change 20 to whatever you may like.
#include <iostream>
using namespace std;
int main()
{
char Ch[20];
char * pCh;
pCh = Ch;
cout << "What is your name?" << endl;
cin >> pCh;
cout << "Hello, " << pCh << "!" << endl;
return 0;
}
Try that and see if it works for you... If you don't understand something just ask.
To be clear, I'm definitely not trying to actually do anything :-)
So I'll always need to make a buffer for a string?
How come it will actually spit my name back out in the last cout... statement, but segfaults? What causes the segfault?
goon12
06-09-2005, 06:50 PM
Did you try debugging it with gdb? You can often find the reason why it's crashing using a debugger, and it doesn't hurt to get familiar with debugging. I copy and pasted your code and it compiled with no warnings, and ran fine.
myprompt> ./foo
What is your name?
goon12
Hello, goon12!
myprompt>
I'm using g++ (GCC) 3.3.4.
-goon12
I get this:
What is your name?
Me
Hello, Me!
Segmentation fault
gdb says this:
(gdb) run
Starting program: /home/nathan/tmp/a.out
What is your name?
Me
Hello, Me!
Program received signal SIGSEGV, Segmentation fault.
0xb7ff6e1b in _dl_init () from /lib/ld-linux.so.2
(gdb) cont
Continuing.
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb)
Of course, I only know these two gdb commands, run and cont :-)
bwkaz
06-09-2005, 07:11 PM
Rule Number One: When you overwrite random addresses, you will NOT always see a segfault immediately!
It can be delayed until something returns through those addresses (at which point your code will jump off into never-never land). It can be delayed until the next call to free(). It can even sometimes be delayed until the process exits (though that may have only been under DOS; maybe not Linux).
In gdb, try bt (backtrace). This will tell you which functions called down to the one that you're currently in (_dl_init), so you can maybe tell what went wrong up farther. On the other hand, since you overwrote the contents of random memory with your read-into-a-pointer-to-nothing call, it may very well not be obvious.
Now, as to what you're trying to accomplish, this is how I'd do it (in C++ at least):
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
int main()
{
std::string name;
cout << "What is your name?" << endl;
cin >> name;
cout << "Hello, " << name << "!" << endl;
return 0;
} Use the std::string class to hold strings. That's what it was created for! ;) You don't have to worry about allocation or any of that -- the methods of std::string that get called (or the overload of operator >>) automatically grow the string as needed.
Thanks!!!! This thread has learned me a number of lessons I wish I'd had every previous time I'd tried to bother to learn C++!!!!!
JKlebs9225
06-10-2005, 02:05 AM
well, from what my computer science teacher tells me, a segmentation violation is caused when a program tries to access memory that does not belong to it. Every process is given a certain amount of memory to run in by the operating system. So called "dangling pointers", pointers that are not assigned to any address, are a common cause of segment violations because they are filled with a "junk value" when declared but not initialized. This junk value may or may not be memory allocated to your program. You created a dangling pointer when you wrote:
char * pCh;
At pointer should always be initialized to some address, such as:
char ch;
char * pCh = &c; // read &c as "the address of c"
or to zero, a null pointer:
char * pCh = 0;
if this is not done when you declare a pointer, you will likely forget about them, and that will sometimes cause a segment violation.
pezplaya
06-10-2005, 02:59 AM
or to zero, a null pointer:
char * pCh = 0;
null is not zero, so u can use this:
char * pCh = NULL;
jacobb
06-10-2005, 11:37 AM
NULL is just a macro that expands to 0, or maybe ((void*)0) in C.
bwkaz
06-10-2005, 06:41 PM
Yes, NULL is always zero. If you compare a NULL pointer to the value zero (without casts in C, or with casts in C++), the comparison will always succeed. That's one of the guarantees of the C virtual machine (such as it is).
The C virtual machine is very, very, very close to the real machine, but a few things (like the value of NULL) are abstracted away.
See this comp.lang.c FAQ entry (http://www.eskimo.com/~scs/C-faq/q5.2.html), and also this (http://www.eskimo.com/~scs/C-faq/q5.5.html) one.