uKolka
uKolka

Reputation: 38670

Dereference NULL pointer in C++

So I'm trying to get familiar with c++. And here is the task that is supposed to exercise usage of pointers. Here is how it goes:

Write a function that prompts the user to enter his or her first name and last name, as two separate values. This function should return both values to the caller via additional pointer. It should prompt for the last name only if the caller passes in a NULL pointer for the last name.

I've tried a few versions. The one I'm stuck with now is:

#include <iostream>
#include <string>

using namespace std;


void getFullName(string *p_first, string *p_last) {
    cout << "First name:";
    getline(cin, *p_first);
    if (!p_last) {
        cout << "Last name:";
        getline(cin, *p_last);
    }
}


int main() {

    string first;
    string *p_first = &first;
    string *p_last = NULL;

    getFullName(p_first, p_last);

    cout << *p_first << endl << *p_last << endl;
    return 0;
}

Well, it crashes. And I've tried to pass a reference to the 'last' and then pointing to it. But after exiting the function the pointer is NULL again.

Upvotes: 2

Views: 2538

Answers (5)

hyde
hyde

Reputation: 62777

First of all, the assignment is faulty (if that is the complete assignment), or your interpretation of the assignemnt is faulty. Here's a version which will read last name, if p_last points to a string where it should be stored:

void getFullName(string *p_first, string *p_last) {
    cout << "First name:";
    getline(cin, *p_first);
    if (p_last) {
        cout << "Last name:";
        getline(cin, *p_last);
    }
}

Here's a version which use p_last as last name if it's not NULL, otherwise reads last name from user, and in both cases returns full name in p_first:

void getFullName(string *p_first, string *p_last) {
    cout << "First name:";
    getline(cin, *p_first);
    string lastname;
    if (!p_last) {
        cout << "Last name:";
        getline(cin, lastname);
    } else {
        lastname = *p_last;
    }
    *p_first += lastname;
}

Here's a version, which uses reference to pointer to alter p_last if it is NULL

void getFullName(string *p_first, string *&p_last) {
    cout << "First name:";
    getline(cin, *p_first);
    if (!p_last) {
        p_last = new string;
        cout << "Last name:";
        getline(cin, *p_last);
    }
}

None of these match your assignment though.

Upvotes: 0

Bart van Ingen Schenau
Bart van Ingen Schenau

Reputation: 15768

I think there is an error in the text of the exercise and it should read:

Write a function that prompts the user to enter his or her first name and last name, as two separate values. This function should return both values to the caller via additional pointer. It should prompt for the last name only if the caller passes in a non-NULL pointer for the last name.

As it stands, your code causes undefined behaviour by dereferencing a null pointer

void getFullName(string *p_first, string *p_last) {
    cout << "First name:";
    getline(cin, *p_first);
    if (!p_last) {    /* <-- This test should be inverted */
        cout << "Last name:";
        /* Now, you get here only when p_last == NULL. On the next line, 
         * you dereference that null-pointer and try to read a string into 
         * non-existing memory: recipe for disaster.
         * With the condition inverted, you would only get here if you have 
         * a string to store the text in. */ 
        getline(cin, *p_last);
    }
}

Upvotes: 7

Jack Aidley
Jack Aidley

Reputation: 20107

The reason it is not working is because the call to getline takes a string reference (basic_string<>&) as the second argument, you're dereferencing a null pointer and passing it through. This is pretty much always going to give an error. You would need to new a fresh string to pass through to it, but this is a bad idea because it's pretty much guaranteed to lead to a memory leak since you've given yourself no way to pass it back.

Where you're passing a pointer expecting the value it points to to be altered and thus act as a return value you need to provide a valid pointer.

Upvotes: 0

Moo-Juice
Moo-Juice

Reputation: 38825

Given that your question states you use an additional, I would write it as:

string getFullName()
{
    string first, last;
    cout << "First name:";
    getline(cin, first);
    cout << "Last name:";
    getline(cin, last);
    return first + last;  // note use of additional
}

Upvotes: 0

Luchian Grigore
Luchian Grigore

Reputation: 258568

Don't use pointers, you don't need pointers for this. Just pass the parameters by reference:

void getFullName(string& p_first, string& p_last) 

However, the problem is you're dereferencing p_last which is NULL -> undefined behavior:

if (!p_last) {  //this evaluates to true, because p_last==NULL
    cout << "Last name:";
    getline(cin, *p_last);
}

Upvotes: 0

Related Questions