Can someone see why this is crashing at runtime?

This is a discussion on Can someone see why this is crashing at runtime? within the C++ Programming forums, part of the General Programming Boards category; Sorry my description is not a bit more detailed, but I just haven't got a clue why this is crashing. ...

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    11

    Can someone see why this is crashing at runtime?

    Sorry my description is not a bit more detailed, but I just haven't got a clue why this is crashing. I am a complete newb (I"m just teaching myself), so hopefully one of you more experienced guys will spot the problem quickly.

    The crash is occurring in the overloaded << operator function contained within road.cpp. The crash is occurring when I try and cout the variable rCar (if I comment that bit out, it doesn't crash).

    Hopefully the code is fairly self-explanatory. Obviously it's nothing useful, just me trying to get my head around the language.

    Thanks in advance.


    main.cpp
    Code:
    #include <iostream>
    #include "car.h"
    #include "road.h"
    
    
    using namespace std;
    
    
    int main()
    {	
    	Car c(1962, "EK", "Holden");
    	cout << c << endl;
    	
    	Road r("Maitland");	
    	cout << r << endl;
    	
    	cout << "Adding the car..." << endl;
    	
    	r.add(&c);
    	cout << r << endl; 
    }


    car.h
    Code:
    #ifndef CAR_H
    #define CAR_H
    #include <string>
    #include <ostream>
    
    
    using namespace std;
    
    
    class Car
    {
    	public:
    		const short m_nYear;
    		const string m_strModel;
    		const string m_strMake;		
    		Car(short, string, string);
    		friend ostream& operator <<( ostream&, Car c );
    
    
    	private:
    
    
    	protected:
    
    
    };
    
    
    #endif // CAR_H

    car.cpp
    Code:
    #include "car.h"
    #include <iostream>
    
    
    using namespace std;
    
    
    
    
    Car::Car(short year, string model, string make) : m_nYear(year), m_strModel(model), m_strMake(make)
    {	
    	cout << "Car constructed: " << (*this) << "." << endl;
    }
    
    
    ostream& operator <<( ostream& outputStream, Car c )
    {
    	outputStream << c.m_nYear << " " << c.m_strModel << " " << c.m_strMake;
    	return outputStream;
    }

    road.h
    Code:
    #ifndef ROAD_H
    #define ROAD_H
    #include "car.h"
    #include <iostream>
    #include <ostream>
    
    
    using namespace std;
    
    
    class Road
    {
    public:
    	Road( string );
    	~Road();
    	const string m_strName;
    	friend ostream& operator <<(ostream&, Road);
    	void add(Car* c);
    	
    private:
    	Car* m_pcCar;
    
    
    };
    
    
    #endif // ROAD_H

    Code:
    #include "road.h"
    #include "car.h"
    #include <iostream>
    
    
    using namespace std;
    
    
    Road::Road(string name) : m_strName(name)
    {
    	cout << (*this) << " was created." << endl;
    }
    
    
    Road::~Road()
    {
    }
    
    
    
    
    void Road::add(Car* pCar)
    {
    	this->m_pcCar = pCar;	
    }
    
    
    
    
    ostream& operator <<( ostream& outputStream, Road r )
    {
    	Car& rCar = *(r.m_pcCar);
    	
    	if (r.m_pcCar)
    		outputStream << r.m_strName << " road, featuring a " << rCar; // <-- causes CRASH!!!
    	else 
    		outputStream << r.m_strName << " road";
    	return outputStream;
    }

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,208
    Road's constructor does not initialise m_pcCar. m_pcCar is therefore an uninitialised pointer until it is later changed. Accessing its value causes undefined behaviour.

    Your code in main() exhibits multiple accounts of undefined behaviour because of this.
    Code:
        Road r("Maitland");
        cout << r << endl;
    The first case of undefined behaviour is that Road's output stream operator passes a copy of r to the streaming operator. Creating a copy of r accesses values of r's members, including m_pcCar.

    The second case of undefined behavuour is that Road's output stream operator creates a reference (rCar) from r.m_pcCar in the statement "Car& rCar = *(r.m_pcCar);" Doing that accesses r.m_pcCar (albeit the r in the streaming operator is a COPY or r in main()). The reference rCar is therefore invalid, and should not be used.

    The third case of undefined behaviour is in the "if (r.m_pcCar)" which, again, accesses the value of r.m_pcCar.

    The fourth case of undefined behaviour is in the statement "outputStream << r.m_strName << " road, featuring a " << rCar;". As I said above, the reference rCar is invalid, so should not be used. In fact, your code uses it. That is, again, undefined behaviour.


    The thing is all instances of undefined behaviour in a program can cause a crash (although they don't have to). Your code exhibits multiple instances of undefined behaviour (four that I've found on a quick look). Any or all of them can cause a crash. It just so happens that the fourth instance of undefined behaviour gives a crash, with your compiler.
    Right 98% of the time, and don't care about the other 3%.

  3. #3
    Registered User
    Join Date
    Oct 2012
    Posts
    11
    Thankyou very much for taking the time to help me out. I appreciate that enormously.

    I was able to solve the crashing problem, simply by initiating m_pcCar to 0 (null pointer). I hope this is the correct way to go about things.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,208
    That will probably eliminate the crash in your code.

    However, your code still exhibits undefined behaviour by doing
    Code:
    ostream& operator <<( ostream& outputStream, Road r )
    {
        Car& rCar = *(r.m_pcCar);
         
        if (r.m_pcCar)
            outputStream << r.m_strName << " road, featuring a " << rCar;
        else
            outputStream << r.m_strName << " road";
        return outputStream;
    }
    If r.m_pcCar is a NULL pointer (which is what initialising to zero achieves) then creating a reference from it (aka dereferencing it) still yields undefined behaviour. It is just a different from of undefined behaviour than you had before.

    You can eliminate that undefined behaviour (assuming your constructors always initialise m_pcCar to NULL) by
    Code:
    ostream& operator <<( ostream& outputStream, Road r )
    {
        if (r.m_pcCar)
            outputStream << r.m_strName << " road, featuring a " << *(r.m_pcCar);
        else
            outputStream << r.m_strName << " road";
        return outputStream;
    }
    The problem with undefined behaviour is that anything is allowed to happen. Including your program appearing to run correctly, with your current compiler, and failing when you port it to another compiler (or, even, upgrading your compiler to a newer version).

    There are other concerns with your code (unrelated to your problem) but I'll leave them for someone else to comment on.
    Last edited by grumpy; 11-07-2012 at 12:02 AM. Reason: Forgot to dereference a pointer
    Right 98% of the time, and don't care about the other 3%.

  5. #5
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,296
    When your class has nothing to do from the destrutor and the destrutor does not need to be virtual, then just don't write it, or in your case, delete it.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  6. #6
    Registered User
    Join Date
    Oct 2012
    Posts
    11
    Thankyou very much guys.

    grumpy: that makes sense, thanks.

    iMalc: that was put there by the IDE. I usually delete it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. crashing
    By Tool in forum C++ Programming
    Replies: 4
    Last Post: 07-11-2010, 01:23 PM
  2. Crashing
    By SanderK in forum C++ Programming
    Replies: 1
    Last Post: 03-24-2009, 05:41 PM
  3. Runtime formation and execution at runtime
    By Soham in forum C Programming
    Replies: 17
    Last Post: 08-27-2008, 08:45 AM
  4. Crashing...
    By webren in forum C++ Programming
    Replies: 3
    Last Post: 04-17-2005, 01:09 AM
  5. crashing code
    By lambs4 in forum C Programming
    Replies: 2
    Last Post: 06-09-2003, 10:09 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21