Initializing structure variable members in class gives segmentation fault - c++

Yes, I know it's a duplicate of like a hundred questions, but I have been working on this for hours and nothing is working.
All I want to do is initialize some private variables inside a class definition.
The structure looks like this:
#include <string>
using namespace std;
typedef string DataType;
class Slist {
public:
private:
// private data type: Node
struct Node {
DataType data;
Node *next;
};
// state variables:
Node *head, *tail, *cursor;
};
I am initializing them like so:
Slist::Slist (void) {
cursor -> data = 'n';
cursor -> next = new Node;
And this is giving me a segmentation fault. I know this means I am trying to access memory that doesn't exist, but despite these being private variables, I am trying to access them in the Slist CONSTRUCTOR, which would of course have access to them. If someone would tell me what is up I would be extremely grateful.

You did not initialize or assign the pointer to a memory location. Any pointer requires valid memory location to work with.
you can do
cursor = new Node;
Before using the arrow operator.

Related

Why do binary trees have a node pointer inside of them, instead of just another node? Also, why is the creation function to this tree a pointer? [duplicate]

I'm trying to speed up a python routine by writing it in C++, then using it using ctypes or cython.
I'm brand new to c++. I'm using Microsoft Visual C++ Express as it's free.
I plan to implement an expression tree, and a method to evaluate it in postfix order.
The problem I run into right away is:
class Node {
char *cargo;
Node left;
Node right;
};
I can't declare left or right as Node types.
No, because the object would be infinitely large (because every Node has as members two other Node objects, which each have as members two other Node objects, which each... well, you get the point).
You can, however, have a pointer to the class type as a member variable:
class Node {
char *cargo;
Node* left; // I'm not a Node; I'm just a pointer to a Node
Node* right; // Same here
};
Just for completeness, note that a class can contain a static instance of itself:
class A
{
static A a;
};
This is because static members are not actually stored in the class instances, so there is no recursion.
No, but it can have a reference or a pointer to itself:
class Node
{
Node *pnode;
Node &rnode;
};
Use a pointer, & better initialized:
class Node {
char * cargo = nullptr;
Node * left = nullptr;
Node * right = nullptr;
};
Modern C++
It is a better practice to use smart-pointers (unique_ptr, shared_ptr, etc.), instead of memory allocations by 'new':
#include <string>
#include <memory> // For 'std::unique_ptr'
class Node {
public:
std::string cargo;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
};
int main()
{
auto bt = std::make_unique<Node>();
(*bt).cargo = "Coffee";
(*bt).left = std::make_unique<Node>();
}

Cannot copy struct's items into another struct

I have struct Node and struct UniqueInstructor. Both are singly-linked lists. I have already filled struct Node with some values. Now what I need to do is fill the second UniqueInstructor struct with Node's struct specific value (std::string instructor).
This is how my structs look like:
// main struct that I already filled with data
struct Node {
Node* pNext;
std::string data1;
std::string data2;
std::string day;
std::string group;
std::string instructor; // these are the items I want to copy
// into the UniqueInstructor struct
std::string course;
};
// my 'target' struct, also linked list
struct UniqueInstructor {
UniqueInstructor* pNext;
std::string instructor;
};
For now, all I need to do is copy all the std::string instructor values from Node into UniqueInstructor.
I have tried bunch of things, such as:
void DuplicateInstructor(Node *&pHead)
{
pHead = new UniqueInstructor { pHead, pHead->instructor };
}
but I am getting errors. In this case:
cannot convert 'Node*' to 'UniqueInstructor*' in initialization
My problem probably lies somewhere in passing struct into that function. Please be forgiving, I am fresh-new to structs and pointers. Thank you for help.
You just need to copy the Node::instructor field into the UniqueInstructor::instructor field. Both fields are std::string so that is no problem.
void like_this(Node& n, UniqueInstructor& i)
{
i.instructor = n.instructor;
}
Now it's not very clear what you actually trying to achieve and what your program structure is so I can't tell you where or how you get the Instructor object. In the example above both objects exist. Also you can't link a Node with an UniqueInstructor. Simply Node::pNext and UniqueInstructor::pNext are of completely different types, so I don't know what you are trying to do here.
Moreover explicit new / delete calls are a very bad practice. They have absolutely no place in C++ (outside of library implementations). Too much headache and more importantly too much room for bugs (memory leaks on exceptions). Please read about RAII and smart pointers in C++.

Creating a non-binary tree structure in C++

I need help creating a non-binary tree structure. This structure must contain a class node with as many pointers to node as a the node needs. This is where I get confused.
Here is my class node:
class nodo{
public:
int id;
char info[255];
nodo **son,*father;
nodo()
{
strcpy(info,"");
son=(nodo*)malloc(sizeof(nodo));
}
};
As far as I understand, each time I need a new son pointer I must do the following code:
son=(nodo*)realloc(sizeof(nodo)*t)
t being the number of nodes I want to add plus 1. I canĀ“t seem to understand how to access the pointers. For example, I've already added 2 sons and I want to access the second one, how should I do it?
Is there any other approach to the problem?
Any help will be thanked.
You're writing C++, not C. Don't try to re-implement your own dynamic array from the ground up. The standard library already has std::vector to handle that for you.
class nodo{
public:
int id;
std::string info;
nodo *parent;
std:::vector<nodo *> children;
nodo(nodo *parent) : parent(parent)
{
}
void add_child(nodo *child) { children.push_back(child); }
};
You're trying to dynamically create an array of child pointers for each node. This approach is fine as long as you know how many children the node will have beforehand.
Your constructor should look something like this:
nodo(int numsons) {
son = new nodo*[numsons];
}
This will allocate an array of child nodes, which you will need to delete in the deconstructor.
If you don't know how many children the node will have beforehand (when you call the constructor), you should use a vector.

C++ "Getter" method throwing access violation when trying to return private variable in same class

The problem I'm having is that the "getter" method in my code is throwing an Access Violation Exception whenever it tries to return the variable it's designed for. I included the constructor below since the last line (the cout) does not cause an access violation. LinkedNode is a header file.
#ifndef _LinkedNodeClass_
#define _LinkedNodeClass_
#include <iostream>
#include <string>
using namespace std;
class LinkedNode {
public:
LinkedNode(string first, string last, int ID, LinkedNode* rightNode, LinkedNode* leftNode)
{
Fname = first;
Lname = last;
EID = ID;
right = rightNode;
left = leftNode;
cout<<"LNODE EID: "<<EID<<endl; //Does not cause access violation
}
int getEID()
{
return EID; //Does cause access violation
}
private:
string Fname;
string Lname;
int EID;
LinkedNode *right;
LinkedNode *left;
};
#endif
The LinkedNode object is being pointed to by a LinkedNode pointer called head. Here's the code from the class using LinkedNode:
#include <iostream>
#include <fstream>
#include <string>
#include "LinkedNode.h"
using namespace std;
class MJCTree
{
private:
LinkedNode* head;
int size;
public:
MJCTree()
{
head = 0; //not sure how to null.
size = 0;
}
void insert(string first, string last, int bEID)
{
if(size == 0)
{
head = new LinkedNode(first, last, bEID, 0, 0);
++size;
}
}
int getFirst() //This method leads to the Access Violation
{
return head->getEID();
}
};
and the Exception:
First-chance exception at 0x013821f6 in Project 3.exe: 0xC0000005: Access violation reading location 0xcccccd0c.
Unhandled exception at 0x013821f6 in Project 3.exe: 0xC0000005: Access violation reading location 0xcccccd0c.
Your LinkedNode class looks ok, but your MJCT class is dangerous.
The getFirst method uses head, but there's no guarantee that head has been
initialized. The MJCTree constructor does not initialize it, and if you haven't
yet called insert, you'd likely get an access violation.
A class constructor should initialize an object and leave it in a state that is safe to use. Your MJCTree constructor does not do that, because a call to the getFirst function will use a null (or previously uninitialized) pointer. You could either modify the constructor so that it allocates a head node for getFirst to use. Or you can modify getFirst so it is safe to call even though head is null, by adding a check for size>0 or head!=0. If that check fails you can't use head and either need to return an error or throw an exception.
We would need to see the code that creates an MJCTree instance and calls getFirst in order to tell exactly what is going wrong, but designing a class that can be used safely/correctly is more important.
The head you mentioned should point to a LinkedNode object, so you must make sure you have do this action such as
head = new LinkedNode(...);
It seems like you did not initialize your head pointer.
It might help to post more code, showing how you declared head, and how you are initializing it (or fail to do so). Remember that a pointer points to something, and if you did not initialize it, it points to, well, nothing, and accessing its contents
Your LinkedNode class is perfectly fine.
You are calling accessor method on an uninitialized, destroyed or otherwise invalid LinkedNode instance at an address around 0xcccccd0c.
A likely scenario, is that you did not create anything for your head pointer to point to, but it's hard to know more precisely without having more code to look at.
The code you see is all correct, it was the code in my main.cpp that was the issue. I was passing my MJCTree by value and not by reference to my insert function, which meant I never actually inserted anything into my tree. Yep, I'm used to Java.

c++ store items into an array

I have this code that in my mind, it recieved an item called Vehicle and it has to store it in an array called Node. This is the code related to this part of the program:
void Table::process(Vehicle v, int cont) {
char a='A'+cont;
putVehicle(a,v);
Node.a_v[cont]=v;
if(cont==0) a_surt=v.rowVehicle();
}
This is how I have the array on the private part of Table.h:
struct Node{
Vehicle a_v;
};
The error I get is:
error: expected primary-expression before '.' token
I have the includes I need, but everytime I type this: Node.a_v It gives me that error.
Any advice?
If you want to use a struct, you need to declare a Node before using it. Also, the struct needs to contain an array (or better, look into vectors for more flexibility).
struct Node {
Vehicle[10] a_v; // 10 is max number of Vehicles in array
};
Node myNode;
myNode.a_v[cont] = v;
Remember that if you want to keep this Node around and put more things in it, it needs to be declared in the right scope. For example, to have your process function add a Vehicle to a Node that exists outside of the function process, you could something like this:
void Table::process(Node n, Vehicle v, int cont) {
char a = 'A'+cont;
putVehicle(a,v);
if (cont < 10) {
n.a_v[cont] = v;
}
if (cont == 0) a_surt = v.rowVehicle();
}
It kind of looks like you're just trying to use an array. In that case you're looking for something like this:
// This would go somewhere in your program. Again, 10 is just an example.
Vehicle vehicleArray[10];
// Send this array to this function
void Table::process(Vehicle[] vArray, Vehicle v, int cont) {
char a = 'A'+cont;
putVehicle(a,v);
if (cont < 10) { // In a real program, don't hard-code array limits.
vArray[cont] = v;
}
if (cont == 0) a_surt = v.rowVehicle();
}
You should use Node object to get access to the a_v variable. This line
Node.a_v[cont]=v;
Is incorrect. You should do something like that:
Node n;
n.a_v[cont]=v;
everytime I type this: Node.a_v It gives me that error.
Node is a type; types define the structure of a objects, but they do not have fields of their own (except the static fields, which belong to all instances at once; they are accessed differently anyway).
In order to use a . or -> operator, you need an instance of a Node, like this:
Node x;
x.a_v = ...
It is not clear in your case from where the Node instances should be coming, though. In order to access them, you would need to either pass them in as parameters, or make them available statically/globally (not recommended).
Okay, so Node is NOT the name of your array. It's the name of a user-defined type that is supposed to contain an array. Your Node, however, does not contain an array. It contains one Vehicle, named a_v. I assume a_v is supposed to represent an Array of Vehicles. Therefore, you need to allocate the array. Something like this:
struct Node {
Vehicle a_v[AMOUNT];
};
If you don't know at compile-time how large you want your arrays to be, then they must be dynamically allocated, like this:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
};
If it's dynamically allocated, then it must also be deallocated:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
~Node() {
delete[] a_v;
}
};
AND if it's dynamically allocated, you need to add provisions for copying or disable copying:
struct Node {
Vehicle* a_v;
Node() {
a_v = new Vehicle[AMOUNT];
}
~Node() {
delete[] a_v;
}
// Disable copies (with C++11 support):
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
// Disable copies (without C++11 support) by making them private and not defining them.
private:
Node(const Node&);
Node& operator=(const Node&);
};
Then to access one of the Vehicles, you'd need to do so like this:
Node n; // Declare a node, which contains an array of Vehicles
n.a_v[cont] = v; // Copy a Vehicle into the array of Vehicles
Note, however, that if you declare the Node instance in this function, then it is local and it will go out of scope as soon as your function ends. You need to declare the Node instance as a member of your Table if you want it to persist past the function call.
class Table
{
private:
Node n;
};
Lastly, as others have suggested, I'd highly recommend that you read a C++ book to learn C++. My personal recommendation is this book (5th edition, don't buy 6th or 7th - the author of those editions is terrible).