0

The following program compiles with g++ but then crashes upon running:

class someClass
{
public:
    int const mem;
    someClass(int arg):mem(arg){}
};

int main()
{
    int arg = 0;
    someClass ob(arg);

    float* sample;
    *sample = (float)1;

    return 0;
}

The following program does not crash:

int main()
{

    float* sample;
    *sample = (float)1;

    return 0;
}
user383352
  • 5,033
  • 4
  • 25
  • 20
  • 5
    Do you have a good C++ book? If you do, it should discuss in considerable depth pointers and how they are used. If you don't, I would strongly recommend getting one of the introductory books listed in [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/). – James McNellis Aug 01 '10 at 16:52
  • No, not yet. What's wrong with learning the hard way? – user383352 Aug 01 '10 at 16:55
  • 3
    @drenami: You really can't learn C++ stumbling through writing programs without a good book to instruct you on the fundamentals. – James McNellis Aug 01 '10 at 17:00
  • 4
    @drenami: "What's wrong with learning the hard way?" You're asking for explanation, but ANY C++ books already explains that stuff. Most people wouldn't want to waste their time explaining simple things you could easily learn by reading a book - info is already available, and telling basics isn't fun. Get a book and read it. You won't get far in C++ without a book anyway. – SigTerm Aug 01 '10 at 17:00
  • 1
    "What's wrong with learning the hard way?" You can't learn anything by trial and error. All you'll can ever do is randomly write code that crashes. The odds of writing code that doesn't crash is quite small. Ask any professional. It takes a great deal of concentrated effort to write code that doesn't crash. Discussing random code isn't helpful to you -- all we can say is "random code can't work". – S.Lott Aug 01 '10 at 17:07
  • 2
    @drenami: "What's wrong with learning the hard way?" And another thing. If you want to spend next 50 years unsuccessfully trying to learn C++ the hard way, I'm not going to stop you. But you should know that C++ has enough extremely tricky concepts that will cause "smoke to go out of your ears" when you encounter them first time, even if you have books and a lot of additional literature. You will __never__ discover and fully understand those concepts while "learning the hard way". If the literature is available, there is no reason to make things needlessly complicated. Get a book. – SigTerm Aug 01 '10 at 17:22

4 Answers4

8
float* sample;
*sample = (float)1;

sample is never initialized to point to an object, so when you dereference it, your program crashes. You need to initialize it before you use it, for example:

float f;
float* sample = &f;
*sample = (float)1;

Your second program is still wrong, even though it does not crash. Dereferencing a pointer that does not point to a valid object results in undefined behavior. The result could be your program crashing, some other data in memory getting overwritten, your application appearing to continue to run correctly, or any other result. Your program could appear to run fine today but crash when you run it tomorrow.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 2
    ... and this is a good reason not to learn 100% "the hard way". You will be on a constant wild goose chase with stuff like this. – tenfour Aug 01 '10 at 16:59
  • It's not irrelevant when you're trying to figure out what's wrong. :) I blame the compiler. – user383352 Aug 01 '10 at 17:00
  • 5
    It's not the compiler's fault you have no clue what you're doing. It's like blaming the hammer because you have the dexterity of a turnip and hit your hand. – Blindy Aug 01 '10 at 17:18
  • 4
    @drenami: " I blame the compiler." Blame yourself. You wouldn't learn how to fly helicopter the hard way and then blame helicopter for crashing, right? – SigTerm Aug 01 '10 at 17:33
4

After a bit of thinking, I can tell you with some degree of certainty why the 2nd example didn't crash.

When a program is executed, the crt (c runtime) pushes on the stack 3 values: the number of arguments (int), the arguments as a char ** and the environment strings also as a char **, then calls main.

Now when you write your main function, as far as I know it always reads the first 2 values and passes them to the arguments of the function, if there are any. If you include the 3rd argument, it passes the 3rd value too, otherwise it's left on the stack. So the stack at the start of the program looks like this:

+--------+
| # args |  
+--------+    
|  args  |  
+--------+  <------ stack pointer
|  envs  |  
+--------+  

In the first example, you allocate the int and the struct on the stack, then the pointer, so the full stack in the first example looks like:

+--------+
| # args |  
+--------+    
|  args  |  
+--------+  <------ stack pointer
|  arg   |  <------ your integer, initialized in code
+--------+  
|   ob   |  <------ your struct, initialized in code
+--------+  
| sample |  <------ your pointer, uninitalized = garbage
+--------+  

So sample is pure garbage and attempting to dereference it crashes your program.

Now in the second example, the stack looks like this:

+--------+
| # args |  
+--------+    
|  args  |  
+--------+  <------ stack pointer
| sample |  <------ pointer, uninitalized (!)
+--------+  

The pointer is still uninitalized, but the value it overwrote is envp, which is an actual pointer to an array: char **. When you dereference it, you get back an array of "pointers to char", so you can overwrite it safely (as long as you don't try to treat this as the original pointer anymore). The memory is allocated and you can use it.

Now this is of course heavily implementation specific, but it seems to fit for your compiler right? You can check with gdb that (char**)sample indeed points to an array of environment variables before you overwrite it.

Screenshot from MSVC++ 10, in 32-bit release mode (debug mode initializes all variables forcefully to prevent this kind of stuff):

the pointer in action http://img651.imageshack.us/img651/5918/69916340.png

Blindy
  • 65,249
  • 10
  • 91
  • 131
0

De-referencing an uninitialized pointer: http://www.cprogramming.com/debugging/segfaults.html

Murali VP
  • 6,198
  • 4
  • 28
  • 36
0

You are dereferencing an unitialized pointer.

The real interesting thing is, why the second example does not crash for you, because it has the same problem

BTW: For me (gcc 4.4, amd64) both example crash.

If you are really interested in why the second example does not crash for you, compile it with debugging information and start it in a debugger.

IanH
  • 3,968
  • 2
  • 23
  • 26