Ok, so im working on an assignment and for the life of me I cannot figure out why I am getting these segmentation faults. Im still in the process of learning c++, programming in general, so I was hoping someone wiser than me can help me out. The program is a self organizing binary search tree and I wasn't having too much difficulty with it until now. Here is the beginning of a main program I am using to test my class BST, I cannot alter the mian program since it is an assignment.
int main() {
string input;
// get a list of integer values
cout << "Enter a list of integer values in one line: ";
getline(cin, input);
cout << "\n**CHECKPOINT 1**\n";
// create a binary search tree
BST<int> bst1(input);
if (!bst1.empty()) {
cout << "\n**CHECKPOINT 2**\n";
cout << "Inorder traversal: ";
bst1.printInOrder();
cout << "Level order traversal: ";
bst1.printLevelOrder();
I have yet to get past the printInOrder() function, here is the code for that
template <typename T>
void BST<T>::printInOrder(BSTNode* t) const
{
if (t->left != NULL)
printInOrder(t->left);
std::cout << " " << t->data << " ";
if (t->right != NULL)
printInOrder(t->right);
}
The really strange thing that is confusing me if that when I add a quick cout<< "Something" to the first line of the printInOrder function, it all of a suddent will the print line
cout << "Inorder traversal: ";
and it will also start printing some of the numbers in the tree before finally giving me a segmentation fault again. :/
So, I would be really grateful if someone could explain to me WTF is going on. The adding or subtracting of a simple cout line shouldn't change things like that should it? Also, I feel like there are better ways of debugging this, if anyone has techniques that they use to figure this stuff out, please share :) Thanks in advance!
EDIT: I have tried the debugger GDB, I was unable to figure it out, but then again im not very well versed in the advanced features of debuggers so I might have missed something.
The only other function that is even run, is the constructor to build from the string input. From what I could tell from the debugger is that the constructor seems to be working fine but nonetheless here's the code
template <typename T>
BST<T>::BST(const std::string input, int th)
{
threshold = th;
root = NULL;
T v;
// Make Input String Stream for easy use of >> operator
std::istringstream iss (input);
do
{
iss >> v;
insert(v, root);
}while(iss.good());
}
EDIT2:
Here is the code for my insert function, Thanks for the help everybody! :)
template <typename T>
void BST<T>::insert(const T& v, BSTNode *&t)
{
if(t == NULL)
{
t = new BSTNode;
t->left = NULL;
t->right = NULL;
t->data = v;
t->searchCount = 0;
}
else if( v < t->data )
insert(v, t->left);
else
insert(v, t->right);
}
There's a marked lack of newlines in your output. Often the line buffering means you don't see anything until a newline is encountered.
I'd modify the line after the PrintOnOrder to this:-
cout << "\nLevel order traversal: ";
In the constructor you are inserting v into the tree even if reading the data with iss >> v failed. Probably you rather want something like this:
while (iss >> v) {
insert(v, root);
}
But probably the real cause for your segmentation fault lies in insert(), for example if that function just inserts a pointer to the (stack allocated) parameter it receives into the tree. The parameter variable will go out of scope at the end of the function (and therefore cease to exist). If you just stored a pointer to that variable into the tree, that pointer will no longer point to anything useful.
I don't see anything wrong here. As others pointed out, output buffering may mean that your code actually completes printInOrder() successfully and then crashes somewhere later.
Related
myclass::myclass(queue<queue<char> > construction_info){
//why does this line crash?
queue<char> first_line_of_construction_info = construction_info.front();
construction_info.pop();
}
I am reading from text files (not generated by me so I can't change the format), into a queue of queue of char. It means lines of characters. And I process that info to generate the class. However, after working in a few debug messages I realized that the first time I am getting a bad_alloc on execute (the program initialized all myclasses from text files at startup) is this line in the code.
I'm new to working with C++ and my google-fu hasn't really helped me with this problem. Does anyone have any suggestions as to where I can start solve this crash?
Simply uncommenting the class constructor is letting my program work without any crashes, obviously without generating actually useful objects of course.
Using g++ with c++11 on linux.
Edit:
Here is the full code cut from the main file:
int initialize_classrooms(){
path p = "files/classrooms/";
//files of lines of queues of chars
//vector of vector of queue of char
vector<queue<queue<char> > > classroom_files;
if(exists(p)){
for (directory_entry& x : directory_iterator(p)){
queue<queue<char> > cur_file;
ifstream file(x.path().filename().string());
queue<char> cur_line;
char ch;
while (file >> noskipws >> ch) {
if(!isspace(ch)){
cur_line.push(ch);
}else if(ch == '\n'){
cur_file.push(cur_line);
cur_line = queue<char>();
}
}
classroom_files.push_back(cur_file);
cur_file = queue<queue<char> >();
file.close();
}
}else{
cout << "Classroom files are missing!" << endl;
return 1;
}
cout << "Got all the way to classroom creation" << endl;
int i = 1;
for(auto cf : classroom_files){
cout << "Number of loops: " << i << endl;
i++;
shared_ptr<classroom> cr = shared_ptr<classroom>(new classroom(cf));
}
cout << "Got past the classroom creation" << endl;
return 0;
}
If the goal is only to read the contents (of the queue at the front), then creating a (constant) reference is preferred.
queue<char> const& first_line_of_construction_info = construction_info.front();
^^^^^^
After "read"ing, it can be poped just as in current code.
EDIT: (Thanks to #Remy Lebeau)
Since copies are wastefule, myclass constructor can take construction_info by reference instead of by value.
myclass::myclass(queue<queue<char> > const& construction_info) {
^^^^^^
Look in the rest of your code too, you probably do not want multiple copies of these queue-of-queues floating around.
Aside: Unless otherwise constrained, instead of using a queue<char> for storing a line of text, consider using std::string.
I am making a program that the user inputs integers and outputs them in reverse. It is a recursive function. The Problem now is that it outputs an infinite of 0's. Please tell me where is the error in my code. and I need some pointers. Please help.
#include <iostream>
using namespace std;
void printreverse(int);
int main()
{
int x;
cout << "Enter numbers: ";
cin >> x;
printreverse(x);
return 0;
}
void printreverse(int x)
{
if(x<10)
cout << x;
else
cout << x%10;
printreverse(x/10);
}
You have wrong identing in printreverse. It should be like this:
void printreverse(int x)
{
if(x<10)
cout << x;
else
cout << x%10;
printreverse(x/10);
}
First it prints x or x%10, then it recurses regardless of what x is. If you wanted more than one statement done in a consequent or alternative you need to use a block. Blocks are denoted with {} in C-decendants. They are so usual that some people actually think conditionals and control flow syntax need to have them. Anyway if the identing was the intended behaviour you should write it like:
void printreverse(int x)
{
if(x<10) {
cout << x;
} else {
cout << x%10;
printreverse(x/10);
}
}
Whenever I use braces on one term in an if I add them for every one even when it's not really needed. Some coding standards, like PSR2, require blocks always to remove the chance of ever getting bugs like this.
C++ is not Python. You need to surround your else block by braces, like so
else
{ // need brace here
cout << x%10;
printreverse(x/10);
} // and here
otherwise only the first statement after the else is being executed (and the final printreverse(x/10) will always be executed, even for 0, so you end up overflowing the stack).
I recommend you to always put braces, even for a single statement in an if/else, precisely for reasons similar to the one you just bumped into.
This is my first time asking something on this site, so if I breach any sort of etiquette, let me know.
I am really new to linked lists and thought that implementing them using the list datatype would be pretty straightforward, but it seems I'm trying to do something weird with them.
I have created a list called "eventList" into which I want to put a series of structs called "entry", and then I wish to put several "eventList"s into an array called "processList".
My issue is that the bit of code
processList[pid].push_front(newEntry);
seems to give me an error. Is there something obviously wrong with what I'm doing?
Here is the code:
#include <iostream>
#include <fstream>
#include <list>
#include <string>
#include <array>
using namespace std;
struct entry {
int eTime;
string eType;
int pid;
};
int main(){
ifstream infile;
string comm;
int num;
entry newEntry;
list<entry> eventList;
array<list<entry>, 1024> processList;
infile.open("input00.txt");
if(infile.is_open()){
while(!infile.eof()){
int pid = -1;
string eTy;
int eTi;
infile >> eTy;
infile >> eTi;
if(eTy == "NEW"){
pid++;
cout << "DB: Process " << pid << endl;
}
else{
newEntry.pid = pid;
newEntry.eType = eTy;
cout << "Type: " << newEntry.eType << " | ";
newEntry.eTime = eTi;
cout << "Time: " << newEntry.eTime << endl;
processList[pid].push_front(newEntry);
//processList[pid] = eventList; <- realized that that wouldn't work fairly quickly
}
}
}
else {
cout << "Sorry, that file doesn't work. :[" <<endl;
}
cout << "Original Order:" << endl;
list<entry>::iterator p = eventList.begin();
while(p != eventList.end()){
cout << p->eType << " For " << p->eTime << "\n"; //This comes from http://www.cplusplus.com/forum/beginner/3396/
p++;
}
//cout << "Ordered By Time:\n";
//eventList.sort(); <- commented out, because I can't get it to work. :[
system ("PAUSE");
return 0;
}
I really love that this resource is available, and I hope that I can follow the logic of any answers that come this way. Apologies for the noobishness, and thanks for looking!
You are initializing pid inside the while loop. So no matter what you do, you will be referencing array[-1]. Talk to you're debugger, it will prove me right.
If eTy != "NEW" then pid remains equal to -1.
So,
processList[pid].push_front(newEntry);
will crash because the subscript is out of bounds ( -1 )
Despite how awesome linked lists are, don't use list (or std::list without the "using namespace std" bit). Use vector (std::vector).
std::list provides the same functionality as std::vector except:
list cannot be randomly accessed with the [] operator like vector
list being a double linked list it uses about 4 times the memory as vector for small structures
list is slower to access even in a sequential way than vector. This is due to vector being easier to cache because it's localized.
list is generally being slower than vector in every other aspect too.
The only "advantage" of list that inserting a new element does not invalidate the iterators. But vector indexes are more reliable than iterators any day, so you should never use iterators unless you absolutely need to.
and push_front builds a list in reverse order, you should usually use push_back.
I will start by saying I am reasonably new as a C++ programmer.
However I understand PHP and VBA, so have a good understanding of the aspects of programming fundamentals.
Because I use CSV's quite often in my day to day job, I thought it would be a good learning exercise to write a library that manipulates CSV Files.
I wrote this function:
int getHeaders(ifstream & os, vector<string> & head2){
string STRING;
getline(os,STRING);
cout << STRING << endl;
STRING.erase(remove(STRING.begin(), STRING.end(), '\"'), STRING.end());
string::iterator it = STRING.begin();
int x = 0;
for (int index = 0; it < STRING.end(); it++, index++) {
if (*it == ',') {
head2.push_back(STRING.substr(0,index));
STRING.erase(0,index+1);
cout << endl << head2[x];
cout << endl << STRING;
x++;
}
}
return head2.size();
}
Which is called by the following:
int addRowCount = 0;
vector<string> head1;
ifstream outfile;
outfile.open("default.csv", ios_base::app);
cout << getHeaders(outfile, head1) << endl;
cout << head1[0] << endl << head1[1] << endl;
But when I run the program, the program just dumps a load of random rubbish to the console (and crashes the application)
I am using windows so cannot use valgrind.
Does anyone know why this may be happening? Obviously this "dump" is not what I want the application to do. I am hoping someone can point out the part of my code which would make this happen.
Thanks in advance.
When you call erase on a string, iterators into that string are invalidated, so it is an error to use it after the call to STRING.erase().
Hint: When you look at the documentation for a method on a class that supports iterators, keep an eye out for notes about invalidating iterators. On this page, for example, read the section titled Iterator validity
[not related to the answer, but a style issue: Using ALL CAPS for a variable name like STRING is generally considered bad style in C and C++. All caps names are used for #defined symbols]
So it turns out that head2[1] wasn't set so it was some sort of memory leak.
Here is the finished function after a few further amendments for the advice in the comments section:
int getHeaders(ifstream & os, vector<string> & head2){
string STRING;
getline(os,STRING);
STRING.erase(remove(STRING.begin(), STRING.end(), '\"'), STRING.end());
int strle = count(STRING.begin(),STRING.end(), ',') + 1;
for(int x = 0; x != strle; x++){
if (count(STRING.begin(), STRING.end(), ',') > 0) {
head2.push_back(STRING.substr(0,STRING.find_first_of(',')));
} else {
head2.push_back(STRING.substr(0,STRING.length()));
}
STRING.erase(0,STRING.find_first_of(',')+1);
}
return head2.size();
}
I've implemented a function to display an avl tree after inserting nodes into it like this
template<class nodetype>
void AVLtree<nodetype>::display() const
{
display(Proot);
}
template<class nodetype>
void AVLtree<nodetype>::display(Node<nodetype> * ptr) const
{
if(ptr==0)
return ;
cout<<ptr->value<<" ";
display(ptr->Pleft);
display(ptr->Pright);
}
after compiling,there were no errors ,the program worked but nothing were printed on the screen
help me please....!!
thanks
(Assuming that your tree is built correctly). Screen output is normally line-buffered. You need to output std::endl to std::cout (or at least '\n' character) for something to appear on the screen.
Of course, if your tree is built incorrectly, the root pointer might be null and nothing would be printed for obvious reasons (just a guess).
Finally, even if your tree is built correctly, but all data (ptr->value) is, say, just strings that are empty (for example) or contain only whitespace, then no wonder you can't see anything on the screen.
One technique I like to use is to add delimiters around debug strings:
cout << "-->" << ptr->value << "<--" << endl;
That way, it's easy to distinguish empty output from no output.
You may also want to add something that shows when your entire tree is empty:
void AVLtree<nodetype>::display() const
{
if (Proot)
display(Proot);
else
cout << "empty tree" << endl;
}
If you are printing on a console window, this function may be of use:
void Pause(void)
{
cout << "\nPaused, press ENTER to continue.\n";
cin.ignore(10000, '\n');
return;
}
Call this function before any exit methods or return statements in main.
first of all you need a conceptual overhaul.. Who told you you can compare ptr with 0 ?
Are you trying to suggest that a pointer if nullified is equal to 0 ? Thats totally wrong .. try this :
#include<iostream>
#include<conio.h>
using namespace std;
int main () {
int *p = NULL ;
cout<<*p<<endl;
getch();
return 0;
}
and there your program crashes ... compare ptr with NULL instead of 0 ..