for clarity this bug is from a program for a school assignment but the bug itself is related to problems with malloc rather than understanding the assignment. In the assignment I am only using one instance of this class so the question is mostly for future reference. The problem I am running into occurs when I utilize 2 different instances of my Heap class declared here:
a4.h
#include <iostream>
using namespace std;
/*
Class Declarations
********************************************************************
*/
// A Heap implemented with a growing array
class Heap{
public:
Heap();
~Heap();
void insert ( int item );
int remove();
void printheap();
private:
void trickleup ( int pos );
void trickledown ( int pos );
void swap ( int pos1 , int pos2 );
int* A;
int size;
int capacity;
};
/*
Class Methods
*********************************************************************
*/
// For Heap
Heap::Heap(){
A = NULL;
size = 0;
capacity = 0;
}
Heap::~Heap(){
delete A;
}
void Heap::insert ( int item ){
if ( size == capacity ){
int* newpointer = new int[(capacity*2)+1];
for (int i = 0; i < size; i++) newpointer[i] = A[i];
delete A;
A = newpointer;
}
A[size] = item;
size += 1;
trickleup (size-1);
return;
}
int Heap::remove(){
size -= 1;
int temp = A[0];
swap ( 0 , size );
trickledown (0);
return temp;
}
void Heap::printheap(){
cout << "Root -> [ ";
for (int i = 0; i < size; i++) cout << A[i] << " ";
cout << "]\n";
return;
}
void Heap::trickleup ( int pos ){
int p0 = pos;
int p1 = (pos-1)/2;
if ( p0 == 0 ){
trickledown (0);
return;
}
if ( A[p0] > A[p1] ){
swap ( p0 , p1 );
trickleup ( p1 );
}
else trickledown (p0);
return;
}
void Heap::trickledown ( int pos ){
int p0 = pos;
int p1 = (2*pos)+1;
int p2 = (2*pos)+2;
if ( p1 >= size ) return;
if ( p2 >= size ){
if ( A[p0] < A[p1] ) swap ( p0 , p1 );
return;
}
bool f1 = ( A[p0] < A[p1] );
bool f2 = ( A[p0] < A[p2] );
if ( (A[p1] >= A[p2]) && f1 ){
swap ( p0 , p1 );
trickledown ( p1 );
}
else if ( (A[p1] < A[p2]) && f2 ){
swap ( p0 , p2 );
trickledown ( p2 );
}
return;
}
void Heap::swap ( int pos1 , int pos2 ){
int temp = A[pos1];
A[pos1] = A[pos2];
A[pos2] = temp;
return;
}
The only time I use new to request memory is in the insert function.
The problem occurs when I run my test program compiled from htest.cpp and run both the sections for the h1 test and the h2 test. If I only run one of the two tests the problem does not occur. Here is the test program:
htest.cpp
#include <cstdlib>
#include <iostream>
#include "a4.h"
using namespace std;
int main(){
cout << "\nCreating h1 And h2\n\n";
Heap* h1 = new Heap();
Heap* h2 = new Heap();
cout << "\nAdding 0-6 To h1\n\n";
h1->insert ( 0 ); cout << "h1: "; h1->printheap();
h1->insert ( 1 ); cout << "h1: "; h1->printheap();
h1->insert ( 2 ); cout << "h1: "; h1->printheap();
h1->insert ( 3 ); cout << "h1: "; h1->printheap();
h1->insert ( 4 ); cout << "h1: "; h1->printheap();
h1->insert ( 5 ); cout << "h1: "; h1->printheap();
h1->insert ( 6 ); cout << "h1: "; h1->printheap();
cout << "\nRemoving All Elements From h1\n\n";
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "Removed: " << h1->remove();
cout << " h1: "; h1->printheap();
cout << "\nAdding 6-0 To h2\n\n";
h2->insert ( 6 ); cout << "h2: "; h2->printheap();
h2->insert ( 5 ); cout << "h2: "; h2->printheap();
h2->insert ( 4 ); cout << "h2: "; h2->printheap();
h2->insert ( 3 ); cout << "h2: "; h2->printheap();
h2->insert ( 2 ); cout << "h2: "; h2->printheap();
h2->insert ( 1 ); cout << "h2: "; h2->printheap();
h2->insert ( 0 ); cout << "h2: "; h2->printheap();
cout << "\nRemoving All Elements From h2\n\n";
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "Removed: " << h2->remove();
cout << " h2: "; h2->printheap();
cout << "\n";
return 0;
}
After compiling this program and running it (with the GNU C++ compiler) I get the following output:
Output
Creating h1 And h2
Adding 0-6 To h1
h1: Root -> [ 0 ]
h1: Root -> [ 1 0 ]
h1: Root -> [ 2 0 1 ]
h1: Root -> [ 3 2 1 0 ]
h1: Root -> [ 4 3 1 0 2 ]
h1: Root -> [ 5 3 4 0 2 1 ]
h1: Root -> [ 6 3 5 0 2 1 4 ]
Removing All Elements From h1
Removed: 6 h1: Root -> [ 5 3 4 0 2 1 ]
Removed: 5 h1: Root -> [ 4 3 1 0 2 ]
Removed: 4 h1: Root -> [ 3 2 1 0 ]
Removed: 3 h1: Root -> [ 2 0 1 ]
Removed: 2 h1: Root -> [ 1 0 ]
Removed: 1 h1: Root -> [ 0 ]
Removed: 0 h1: Root -> [ ]
Adding 6-0 To h2
htest: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.
Aborted (core dumped)
I am wondering why the error appears as it doesn't seem like I am doing anything illegal with requesting memory. I would really appreciate it if someone could try to explain the problem clearly as I only have about one year of C++ experience.
*Edit: Changed the destructor Function to not delete size and capacity and added a delete A line to the insert function before re-sizing the array.
Sad that I didn't spot this one before. I'll throw myself onto my sword after answering.
Heap::insert never sets capacity. It stays 0, so inserts after the first do not trigger if (size == capacity) and do not resize A. As a result, A is run out of bounds and trashes the heap (the the memory heap, not the class Heap).
I recommend a small edit:
void Heap::insert(int item)
{
if (size == capacity)
{
capacity = (capacity * 2) + 1; // Note: many tests have shown that 1.5 is a
// better expansion factor than 2.
int* newpointer = new int[capacity];
for (int i = 0; i < size; i++)
newpointer[i] = A[i];
delete A;
A = newpointer;
}
A[size] = item;
size += 1;
trickleup(size - 1);
return;
}
In addition
Heap* h1 = new Heap();
Heap* h2 = new Heap();
do not need to be dynamically allocated and can be defined as
Heap h1;
Heap h2;
Among other advantages temporary allocation brings, such as improved spacial locality, this does not require the programmer to delete h1 and h2, something that is currently not done.
Now if you will excuse me, I must find where I left my sword.
Related
I got a task from my lecture to make association program from my data mining class, and i'm using c++ in microsoft visual studio 2017 since that is the only language i understand.
I'm trying to get support result but all i got is 0. i use an algorithm i got from some sites, but i can't implement it to my code because the value is 0.
I think the problem is in the input data reading, the one with for(int i=0;i<n;i++).
this is my code :
#include<iostream>
#include<string>
using namespace std;
int main()
{
float n = 5, support1 = 0, support2 = 0, support3 = 0;
string item1, item2;
//dataset fixed
string tra1[5] = { "milk", "beer" , "coffee" , "sugar" , "detergen" };
string tra2[5] = { "egg", "flour" , "milk" , "sugar" };
string tra3[5] = { "coffee", "butter" , "cigarette" , "sugar" };
string tra4[5] = { "doritos", "tea" , "coconut oil" , "soap" };
string tra5[5] = { "detergen", "milk" , "sugar" , "coca cola" };
cout << "item 1 : "; cin >> item1;//for example coffee
cout << "item 2 : "; cin >> item2;//for example sugar
cout << endl << "------------------------------" << endl;
//i think this is where the problem is
for (int i = 0;i < n;i++)
{
//tra1
if (item1 == tra1[5]) { support1 + 1; }
if (item2 == tra1[5]) { support2 + 1; }
if (item1 == tra1[5] && item2 == tra1[5]) { support3 + 1; }
//tra2
if (item1 == tra2[5]) { support1 + 1; }
if (item2 == tra2[5]) { support2 + 1; }
if (item1 == tra2[5] && item2 == tra2[5]) { support3 + 1; }
//tra3
if (item1 == tra3[5]) { support1 + 1; }
if (item2 == tra3[5]) { support2 + 1; }
if (item1 == tra3[5] && item2 == tra3[5]) { support3 + 1; }
//tra4
if (item1 == tra4[5]) { support1 + 1; }
if (item2 == tra4[5]) { support2 + 1; }
if (item1 == tra4[5] && item2 == tra4[5]) { support3 + 1; }
//tra5
if (item1 == tra5[5]) { support1 + 1; }
if (item2 == tra5[5]) { support2 + 1; }
else if (item1 == tra1[5] && item2 == tra5[5]) { support3 + 1; }
}
//print how many times are coffee and sugar purchased
cout << "Transaction done " << item1 << " : " << support1 << endl;
cout << "Transaction done " << item2 << " : " << support2 << endl;
cout << "Transaction done " << item2 << " dan " << item2 << " : " << support3 << endl;
cout << endl << "------------------------------" << endl;
float result1,result2,result3;
result1 = (support1 / n) * 100;
result2 = (support2 / n) * 100;
result3 = (support3 / n) * 100;
cout << "Item 1 : " << item1 << "\t" << "Item 2 : " << item2 << endl;
cout << "support " << item1 << " : " << result1 << endl;
cout << "support " << item2 << " : " << result2 << endl;
cout << "support " << item1 << " dan " << item2 << " : " << result3 << endl;
return 0;
}
in your code, inside the loop you keep referencing tra2[5] . I think you mean to use tra2[i] instead. The way you have it now you're only looking at one past the last item in your arrays (arrays are 0-based. Valid indices are [0-4])
2 things, you’re for loop is trying to access the 6th index of the array when it’s only initialized to have 5 indicis.
2nd the support1,2,3 variables are initialized to 0 but you never actually increment those variables, which are used as part of your final calculation.
Your for loop needs to change to have “support1 + 1” be “support1+=1”.
I am trying to return integer from the following method in c++:
int check_for_chef(string str1,string str2,int M,int N)
{
if ( N == -1 )
{
cout << "I am returning 1." <<endl;
return 1;
}
else if ( N > M )
{
cout << " I am returning 0." <<endl;
return 0;
}
else
{
if ( str1[M] == str2[N])
{
location[N] = M;
cout << "location is: "<<location[N]<<endl;
check_for_chef(str1,str2,M - 1, N - 1);
}
else
{
check_for_chef(str1,str2,M - 1, N);
}
}
}
But, what I am getting while returning is :
Returned value is: 35668224
Whole code is here:
#include <iostream>
#include <string>
using namespace std;
int location[4];
int check_for_chef(string str1,string str2,int M,int N)
{
if ( N == -1 )
{
cout << "I am returning 1." <<endl;
return 1;
}
else if ( N > M )
{
cout << " I am returning 0." <<endl;
return 0;
}
else
{
if ( str1[M] == str2[N])
{
location[N] = M;
cout << "location is: "<<location[N]<<endl;
check_for_chef(str1,str2,M - 1, N - 1);
}
else
{
check_for_chef(str1,str2,M - 1, N);
}
}
}
int main()
{
int count = 0;
string original_string;
cin >> original_string;
string chef = "CHEF";
int M = original_string.size();
int N = 4;
while ( 1 )
{
cout << "Returned value is: " << check_for_chef(original_string,chef,M - 1, N - 1);
cout << " i am in while."<<endl;
count++;
original_string.erase(location[3],1);
cout << "the original_string : " << original_string <<endl;
original_string.erase(location[2],1);
cout << "the original_string : " << original_string <<endl;
original_string.erase(location[1],1);
cout << "the original_string : " << original_string <<endl;
original_string.erase(location[0],1);
cout << "the original_string : " << original_string <<endl;
cout << "the original_string : " << original_string <<endl;
M = original_string.size();
cout << "size is :" << M <<endl;
if ( M < N )
break;
}
cout << count <<endl;
}
Please help me to solve this problem.
I don't see two more return in the code
I have added in the commented lines below:
int check_for_chef(string str1,string str2,int M,int N)
{
if ( N == -1 )
{
cout << "I am returning 1." <<endl;
return 1;
}
else if ( N > M )
{
cout << " I am returning 0." <<endl;
return 0;
}
else
{
if ( str1[M] == str2[N])
{
location[N] = M;
cout << "location is: "<<location[N]<<endl;
return check_for_chef(str1,str2,M - 1, N - 1); // here 1st RETURN
}
else
{
return check_for_chef(str1,str2,M - 1, N); // here 2nd RETURN
}
}
}
Your code does not return anything expicitly in the else branch.
Values in x84 usually are returned via EAX register, so if you do not return anything - it behaves like an uninitialized variable.
I used the code from this post, How to display binary search tree in console properly?. It complies fine on my IDE, but it doesnt print out anything so it basically shows nothing. I want it to print out in the tree structure like the post mentioned I posted here. I think I have the code typed wrong for 3rd argument for the printLevel function in int main(). Would char* x = " " work fine? It does give warning message, but I'm not sure if I do it right.
string printLevel(Node *pRoot, int level, string gap)
{
if (level == 1)
{
if (pRoot == 0)
{
cout << ".. printLevel - " << pRoot << ": " << gap << "-" << gap << "\n";
return gap + "-" + gap;
}
stringstream out;
out << pRoot->data;
//cout << ".. printLevel - " << pRoot << ": " << gap << pRoot->data << gap << "\n";
return gap + out.str() + gap;
}
else if(level > 1)
{
string left = printLevel(pRoot ? pRoot->pLeft : 0, level - 1, gap);
string right = printLevel(pRoot ? pRoot->pRight : 0, level - 1, gap);
//cout << ".. printLevel - " << pRoot << ": '" << left << "', '" << right << "'\n";
return left + " " + right;
}
else return
"";
}
void printLevelOrder(Node* pRoot, int depth)
{
for (int i = 1; i <= depth; i++)
{
string gap = "";
for (int j = 0; j < pow(2, depth - i) - 1; j++)
{
gap += " ";
}
string levelNodes = printLevel(pRoot, i, gap);
cout << levelNodes <<endl;
}
}
in the main
Node *pRoot = NULL;
int inputValue = 0;
char* gap = " ";
// Loop to read in input values
cout << "To build a BST enter positive integer values, followed by -1 \n";
while (inputValue != -1)
{
cin >> inputValue;
if( inputValue != -1)
{
insertIntoTree( pRoot, inputValue);
}
}
cout << endl;
// Display the tree
printLevel(pRoot, inputValue, gap);
printLevelOrder(pRoot, inputValue);
I'm trying to use pthread in c++.
I write a mergesort with pthread, but sometimes in pthread_join my code has segmentation fault. ( see codes debug info )
for example, for input:
4
5 1 2 3
output is:
** size is more than 2 **
I'm alive!
create 1: 0
create 2: 0
After creating!
i want to exit ... 2 1
i want to exit ... 2 2
join 1: 0
Segmentation fault
when it want to join pthead number 2, segmentation fault occurs.
Thanks in advance!
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<pthread.h>
using namespace std;
struct toSort
{
int size;
int * arr;
toSort(int _size = 0, int * _arr = NULL)
{
size = _size;
arr = _arr;
}
};
void * mergeSort(void *args)
{
toSort * m = static_cast<toSort*>(args);
if(m -> size == 1)
{
pthread_exit(NULL);
}
else if(m -> size == 2)
{
if(*(m -> arr) > *((m -> arr) + 1))
{
int temp = *(m -> arr);
* (m -> arr) = *((m -> arr) + 1);
* ((m -> arr) + 1) = temp;
}
}
else
{
cerr << "** size is more than 2 **" << endl;
int ind = (m -> size) / 2;
pthread_t t1, t2;
toSort *m1, *m2;
m1 = new toSort(ind, (m -> arr));
m2 = new toSort((m -> size) - ind, ((m -> arr) + ind));
cerr << "I'm alive!" << endl;
cerr << "create 1: " << pthread_create( &t1, NULL, &mergeSort, static_cast<void*>(m1)) << endl;
cerr << "create 2: " << pthread_create( &t1, NULL, &mergeSort, static_cast<void*>(m2)) << endl;
cerr << "After creating!" << endl;
cerr << "join 1: " << pthread_join(t1, NULL) << endl;
cerr << "join 2: " << pthread_join(t2, NULL) << endl;
cerr << "After join!" << endl;
// merge(m -> arr, ind, m -> size);
}
cout << "i want to exit ... " << (m -> size) << " " << (*(m -> arr)) << endl;
pthread_exit(NULL);
return 0;
}
int main()
{
int n, arr[100];
// Read
cin >> n;
for(int i = 0; i < n; i++)
cin >> arr[i];
// Solve
toSort * ans = new toSort(n, arr);
pthread_t getAns;
pthread_create( &getAns, NULL, &mergeSort, static_cast<void*>(ans));
pthread_join(getAns, NULL);
// Write
for(int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return 0;
}
You have a typo
cerr << "create 2: " << pthread_create( &t1, NULL, &mergeSort, static_cast<void*>(m2)) << endl;
You should be using t2 instead of t1 for the second thread.
I used the library streed2006.cpp from source. The code has memory leak in deletion of edges. I cleared the number of edges from hashtable using the following code:
//throwing away the edges from hashtable
for(int t=0;t<HASH_TABLE_SIZE;t++)
{
Edges[t].Remove();
Edges[t].start_node == -1
}
valgrind output:
3,920 bytes in 245 blocks are definitely lost in loss record 9 of 12
==6301== at 0x4029F34: operator new(unsigned int) (in /usr/lib/valgrind /vgpreload_memcheck-x86-linux.so)
==6301== by 0x804A683: Edge::SplitEdge(Suffix&) (suffix_tree.cpp:555)
==6301== by 0x804B02F: AddPrefix(Suffix&, int) (suffix_tree.cpp:753)
Please guide me how to delete the edges.
was able to remove the memory leak. Following is the solution:
void AddPrefix( Suffix &active, int last_char_index )
{
int parent_node;
int last_parent_node = -1;
for ( ; ; ) {
Edge edge;
parent_node = active.origin_node;
if ( active.Explicit() ) {
edge = Edge::Find( active.origin_node, T[ last_char_index ] );
if ( edge.start_node != -1 )
break;
} else { //implicit node, a little more complicated
edge = Edge::Find( active.origin_node, T[ active.first_char_index ] );
int span = active.last_char_index - active.first_char_index;
if ( T[ edge.first_char_index + span + 1 ] == T[ last_char_index ] )
break;
parent_node = edge.SplitEdge( active );
}
Edge *new_edge = new Edge( last_char_index, T.N, parent_node );
new_edge->Insert();
//cout << "Created edge to new leaf: " << *new_edge << "\n";
AddSuffixLink( last_parent_node, parent_node );
if ( active.origin_node == 0 ) {
//cout << "Can't follow suffix link, I'm at the root\n";
active.first_char_index++;
} else {
/*
cout << "Following suffix link from node "
<< active.origin_node
<< " to node "
<< Suffix_Nodes[ active.origin_node ].suffix_node
<< ".\n";
*/
active.origin_node = Suffix_Nodes[ active.origin_node ].suffix_node;
//cout << "New prefix : " << active << "\n";
}
active.Canonize();
delete(new_edge);
new_edge = NULL;
}
AddSuffixLink( last_parent_node, parent_node );
active.last_char_index++; //Now the endpoint is the next active point
active.Canonize();
};
and
int Edge::SplitEdge( Suffix &s )
{
//cout << "Splitting edge: " << *this << "\n";
Remove();
Edge *new_edge =
new Edge( first_char_index,
first_char_index + s.last_char_index - s.first_char_index,
s.origin_node );
new_edge->Insert();
Suffix_Nodes[ new_edge->end_node ].suffix_node = s.origin_node;
first_char_index += s.last_char_index - s.first_char_index + 1;
start_node = new_edge->end_node;
Insert();
//cout << "New edge: " << *new_edge << "\n";
//cout << "Old edge: " << *this << "\n";
delete(new_edge);
//return new_edge->end_node;
return(start_node);
}
void AddPrefix( Suffix &active, int last_char_index )
{
int parent_node;
int last_parent_node = -1;
for ( ; ; ) {
Edge edge;
parent_node = active.origin_node;
if ( active.Explicit() ) {
edge = Edge::Find( active.origin_node, T[ last_char_index ] );
if ( edge.start_node != -1 )
break;
} else { //implicit node, a little more complicated
edge = Edge::Find( active.origin_node, T[ active.first_char_index ] );
int span = active.last_char_index - active.first_char_index;
if ( T[ edge.first_char_index + span + 1 ] == T[ last_char_index ] )
break;
parent_node = edge.SplitEdge( active );
}
Edge *new_edge = new Edge( last_char_index, T.N, parent_node );
new_edge->Insert();
//cout << "Created edge to new leaf: " << *new_edge << "\n";
AddSuffixLink( last_parent_node, parent_node );
if ( active.origin_node == 0 ) {
//cout << "Can't follow suffix link, I'm at the root\n";
active.first_char_index++;
} else {
/*
cout << "Following suffix link from node "
<< active.origin_node
<< " to node "
<< Suffix_Nodes[ active.origin_node ].suffix_node
<< ".\n";
*/
active.origin_node = Suffix_Nodes[ active.origin_node ].suffix_node;
//cout << "New prefix : " << active << "\n";
}
active.Canonize();
//ADDED THIS DELETE HERE
delete(new_edge);
new_edge = NULL;
}
AddSuffixLink( last_parent_node, parent_node );
active.last_char_index++; //Now the endpoint is the next active point
active.Canonize();
};
and
int Edge::SplitEdge( Suffix &s )
{
//cout << "Splitting edge: " << *this << "\n";
Remove();
Edge *new_edge =
new Edge( first_char_index,
first_char_index + s.last_char_index - s.first_char_index,
s.origin_node );
new_edge->Insert();
Suffix_Nodes[ new_edge->end_node ].suffix_node = s.origin_node;
first_char_index += s.last_char_index - s.first_char_index + 1;
start_node = new_edge->end_node;
Insert();
//cout << "New edge: " << *new_edge << "\n";
//cout << "Old edge: " << *this << "\n";
//ADDED THIS DELETE HERE
delete(new_edge);
//return new_edge->end_node;
return(start_node);
}