Reputation: 145
I haven't programmed in C++ in a while, so I've been trying to improve. I have a very simple login function, however it doesn't work. The login function calls getUserAttempts()
which returns a pointer to a struct that contains user details such as username and password. However, any time I try to access the pointer's struct's variables, the program crashes. I feel like I've missed something obvious but can't put my finger on it.
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unordered_map>
typedef std::unordered_map<std::string, std::string> unorderedMap;
typedef struct Credentials {
std::string username;
std::string password;
} structCred;
void login();
structCred* getUserAttempts();
void login() {
unorderedMap credentialMap;
credentialMap["username"] = "mypassword123";
structCred *p;
for (int i = 0; i < 3; i++) {
p = getUserAttempts();
auto it = credentialMap.find(p->username);
std::cout << it->first;
std::cout << it->second;
}
return;
}
structCred *getUserAttempts() {
structCred credentialAttempt;
std::string username, password;
std::cout << "Please enter your username: ";
std::getline(std::cin, credentialAttempt.username);
std::cout << "Please enter your password: ";
std::getline(std::cin, credentialAttempt.password);
return &credentialAttempt;
}
int main() {
std::cout << "Welcome..." << std::endl;
login();
return 0;
}
Upvotes: 0
Views: 84
Reputation: 60288
In this function:
structCred *getUserAttempts() {
structCred credentialAttempt;
// ...
return &credentialAttempt;
}
you are returning an address to a local variable which dies at the end of the function. Accessing the memory is then undefined behavior.
Instead, you should allocate memory for it:
structCred *getUserAttempts() {
structCred *credentialAttempt = new structCred;
// ...
return credentialAttempt;
}
Note that statements like credentialAttempt.username
will have to become credentialAttempt->username
.
However, returning a raw pointer is usually a bad idea, since there is no way of knowing whose responsibility it is to free the memory. Instead, use a unique_ptr
that will take care of freeing the memory for you:
std::unique_ptr<structCred> getUserAttempts() {
auto credentialAttempt = make_unique<structCred>();
// ...
return credentialAttempt;
}
Upvotes: 2
Reputation: 169328
return &credentialAttempt;
This returns a pointer to the function-local variable credentialAttempt
. That doesn't work because the function local is destroyed immediately when the function returns, so the function is returning a pointer to something that no longer exists. Dereferencing the returned pointer is therefore undefined behavior.
Instead, just return the object by value:
structCred getUserAttempts() {
structCred credentialAttempt;
std::string username, password;
std::cout << "Please enter your username: ";
std::getline(std::cin, credentialAttempt.username);
std::cout << "Please enter your password: ";
std::getline(std::cin, credentialAttempt.password);
return credentialAttempt;
}
Upvotes: 3