Seemingly empty vector - c++

I've added some slight multi threading to a simple c++ program and have encountered a few issues along the way.
The latest of these issues is that historical::assignthreads for some reason is receiving an empty vector from the function historical::writeData.
Looking at the code below you will see that writeData iterates through a vector and puts the data in a placeholder before sending it forward to assignthreads (after 5 iterations) - meaning that the vector being sent from writeData to assignthreads shouldn't be empty.
However in assignthreads you will see that there are two cout:s, one before and one after the loop. Both writes to cout without the loop even starting.
Does anyone have any idea of how this could be the case?
void historical::writeData(std::vector<std::vector<std::wstring>> in, const string& symbol) {
std::cout << "Sending data to database connector" << std::endl;
std::vector<std::vector<std::wstring>> temp;
std::vector<std::vector<std::wstring>>::iterator it;
int count = 0;
for (it = in.begin(); it != in.end(); it++) {
if (count = 5) {
cout << "I'm in count 5" << endl;
assignthreads(temp, symbol);
temp.clear();
count = 0;
}
else {
cout << "I'm in count 0" << endl;
temp.push_back(*it);
count++;
}
}
if (!temp.empty()) {
cout << "I'm in empty" << endl;
assignthreads(temp, symbol);
}
else cout << "I'm empty!!" << endl;
}
void historical::assignthreads(std::vector<std::vector<std::wstring>>& partVec, const string& symbol) {
int i = 0;
cout << "I'm in assign" << endl;
vector<thread> threads(size(partVec));
std::vector<std::vector<std::wstring>>::iterator it;
for (it = partVec.begin();
it != partVec.end();
it++) {
cout << "I'm in the loop" << endl;
std::shared_ptr<database_con> sh_ptr(new database_con);
threads.at(i) = std::thread(&database_con::start, sh_ptr, *it, symbol);
i++;
}
cout << "I've finished" << endl;
for (auto& th : threads) th.join();
}
void historical::writer(string* pInput) {
ofstream mf("test.csv");
if (mf.is_open()) {
mf << *pInput;
mf.close();
}
else cout << "Unable to open file" << endl;
}

Your fundamental problem here is that count = 5 is an assignment and is therefore always true. You intended to use count == 5.
It's worth noting that particularly as your vector becomes large copying it is very wasteful, and you're doing this 2 ways:
The vector is passed into writeData by value, change to copying by reference: void writeData(std::vector<std::vector<std::wstring>>& in, const string& symbol)
temp will eventually copy every element of in, use iterators instead so your code would have to change to:
#define SIZE 5
void assignthreads(std::vector<std::vector<std::wstring>>::iterator start, std::vector<std::vector<std::wstring>>::iterator finish, const string& symbol) {
cout << "I'm in assign" << endl;
vector<thread> threads(distance(start, finish));
for(auto i = 0; start != finish; ++i, ++start) {
cout << "I'm in the loop" << endl;
std::shared_ptr<database_con> sh_ptr(new database_con);
threads.at(i) = std::thread(&database_con::start, sh_ptr, *start, symbol);
}
cout << "I've finished" << endl;
for (auto& th : threads) th.join();
}
void writeData(std::vector<std::vector<std::wstring>>& in, const string& symbol) {
std::cout << "Sending data to database connector" << std::endl;
auto count = 0;
while(count < in.size() - SIZE) {
auto start = next(in.begin(), count);
count += SIZE;
auto finish = next(in.begin(), count);
assignthreads(start, finish, symbol);
}
assignthreads(next(in.begin(), count), in.end(), symbol);
cout << "I'm empty!!" << endl;
}

Related

Check if queue is sorted in ascending order hanging

I can't seem to figure out why the program below is not running as intended.
After entering a negative integer value and breaking the first while loop in main, program control does not proceed.
I tried flushing the output stream at various key points but the issue persists.
#include <iostream>
#include <queue>
bool checkValidity(const std::queue<int>& q) {
for(auto i = q.front(); i != q.back(); ++i){
if (q.empty() || q.size() <= 1){
std::cout << "invalid entry, insufficient elements" << '\n';
return false;
break;
}
if (i > ++i) {
std::cout << "invalid entry, not properly sorted" << '\n';
return false;
break;
}
}
std::cout << "valid entry, properly sorted" << '\n';
return true;
}
const char* bool_cast(const bool b) {
return b ? "true" : "false";
}
int main () {
std::queue<int> numbers;
int temp;
std::cout << "Pushing..." << '\n';
while(temp >= 0){
std::cout << "Enter numbers: ";
std::cin >> temp;
if(temp >= 0){
numbers.push(temp);
}
}
bool ck = checkValidity(numbers);
std::cout << bool_cast(ck) << '\n';
std::cout << "{ ";
while(numbers.size() > 0){
std::cout << numbers.front();
numbers.pop();
std::cout << " ";
}
std::cout << "}" << '\n';
return 0;
}
You cannot iterate through the queue, therefore to iterate you need to copy the queue to another queue and then traverse by poping the elements from the queue. and comparing the elements.
Inline comments added for better understanding of the code.
bool checkValidity(const std::queue<int>& q) {
if (q.empty() || q.size() <= 1){ // This can be outside the loop and checked only onces
std::cout << "invalid entry, insufficient elements" << '\n';
return false;
}
std::queue<int> numbers=q; // a new queue to copy the queue
int first=numbers.front(); // to compare we need to variable first and second
numbers.pop();// pop the first value,as it is stored in first variable
int second;
while(!numbers.empty()){
second=numbers.front();
numbers.pop();
if (first> second) { // compare the first and second variable
std::cout << "invalid entry, not properly sorted" << '\n';
return false;
break;
}
first=second; // assign second to first and traverse the reamining queue
}
std::cout << "valid entry, properly sorted" << '\n';
return true;
}
Hope this help.
Inherited from std::queue and use its protected member Container c; to access begin() and end() of the underlying container as previously done here std::queue iteration.
#include <iostream>
#include <queue>
#include <deque>
#include <iterator>
template<typename T, typename Container=std::deque<T> >
class iterable_queue : public std::queue<T,Container>
{
public:
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator const_iterator;
iterator begin() { return this->c.begin(); }
iterator end() { return this->c.end(); }
const_iterator begin() const { return this->c.begin(); }
const_iterator end() const { return this->c.end(); }
};
bool checkValidity(iterable_queue<int>& q) {
if (q.empty() || q.size() <= 1){
std::cout << "invalid entry, insufficient elements" << '\n';
return false;
}
while(q.size()){
auto i = q.begin();
auto j = ++q.begin();
for(; i < q.end() && j < ++q.end();){
std::cout << *i << " " << *j << '\n';
if (*(i) > *(j)) {
std::cout << "invalid entry, not properly sorted" << '\n';
return false;
}
i++, j++;
}
std::cout << "valid entry, properly sorted" << '\n';
return true;
}
std::cout << "invalid entry, insufficient elements" << '\n';
return false;
}
const char* bool_cast(const bool b) {
return b ? "true" : "false";
}
int main () {
iterable_queue<int> numbers;
int temp;
std::cout << "Pushing..." << '\n';
while(temp >= 0){
std::cout << "Enter numbers: ";
std::cin >> temp;
if(temp >= 0){
numbers.push(temp);
}
}
bool ck = checkValidity(numbers);
std::cout << bool_cast(ck) << '\n';
std::cout << "{ ";
while(numbers.size() > 0){
std::cout << numbers.front();
numbers.pop();
std::cout << " ";
}
std::cout << "}" << '\n';
return 0;
}

Debug Assertion Fails On Dynamic Array

So here is my working code for a simple dynamic array. This has to be a sample code for a very entry level data structure implementation:
#include <iostream>
using namespace std;
class AdvancedArray {
public:
AdvancedArray();
~AdvancedArray();
int get_size() const; // get the number of elements stored
double& at(int idx) const; // access the element at idx
void push_back(double d); // adds a new element
void remove(int idx); // remove the element at idx
void clear(); // delete all the data stored
void print() const;
private:
double* elements;
int size;
};
int main()
{
AdvancedArray* arr = new AdvancedArray();
cout << "The Array Size is: " << arr->get_size() << endl;
cout << "Pusing Values: 1.2, 2.1, 3.3, 4.5 in the Array. " << endl;
arr->push_back(1.2);
arr->push_back(2.1);
arr->push_back(3.3);
arr->push_back(4.5);
arr->print();
cout << "The Array Size is: " << arr->get_size() << endl;
cout << "The Element at Index 2 is: " << arr->at(2) << endl;
cout << "Deleting Values: 2.1 from the Array. " << endl;
arr->remove(1);
cout << "The Array Size is: " << arr->get_size() << endl;
arr->print();
cout << "Clearing the Array: " << endl;
arr->clear();
cout << "The Array Size is: " << arr->get_size() << endl;
arr->clear();
return 0;
}
AdvancedArray::AdvancedArray()
{
size = -1;
elements = new double[100]; //Maximum Size of the Array
}
AdvancedArray::~AdvancedArray()
{
delete[] elements;
}
int AdvancedArray::get_size() const
{
if(size < 0)
{
return 0;
}
return size;
}
double & AdvancedArray::at(int idx) const
{
if (idx < 100 && idx >= 0 && size > 0) {
return elements[idx];
}
cout << "Index Out of Bounds." << endl;
}
void AdvancedArray::push_back(double d)
{
if (size >= 100)
{
cout << "Overflow Condition. No More Space!" << endl;
}
else
{
elements[++size] = d;
cout << "Element Pushed In Stack Successfully!" << endl;
}
}
void AdvancedArray::remove(int idx)
{
if (size >= 100 || size < 0)
{
cout << "No Such Element Exists!" << endl;
}
else
{
for(int i = idx; i <size; i++)
{
elements[idx] = elements[idx + 1];
}
size--;
cout << "Element Deleted In Stack Successfully!" << endl;
}
}
void AdvancedArray::clear()
{
delete[] elements;
size = -1;
}
void AdvancedArray::print() const
{
cout << "[ ";
for(int i = 0; i <= size; i++)
{
cout << elements[i] << " ";
}
cout << "]" << endl;
}
So every time I try to run this I have the 2 problems:
What is wrong with my code? Why is the heap getting corrupted (I searched about the error code and that's all has to say)? Is my code doing some major access violations? I am using VS2015.
You do delete [] elements three times without setting elements to nullptr in between. That leads to undefined behavior the second time (and third) time.
When size == 99, the following piece of code attempts to access elements[100]:
if (size >= 100)
{
cout << "Overflow Condition. No More Space!" << endl;
}
else
{
elements[++size] = d;
cout << "Element Pushed In Stack Successfully!" << endl;
}
You need to change ++size to size++.

Infinite Loop while inputting the different data type values in STACK

Below is the code for STACK with no overflow since I am using vector concept. Program seems to be working fine as long as I push integers, but as soon as I push float value (for testing) the output screen goes to infinite loop and debugger doesn't even stop at cin statement and it simply crosses it without giving the control to the console window.
#include"iostream"
class Mystack
{
private:
int *input;
int top;
int capacity;
public:
Mystack();
~Mystack();
void push(int x);
int pop();
int topElement() const;
bool isEmpty() const;
void print();
};
Mystack::Mystack()
{
top = -1;
capacity = 5;
input = new int[capacity];
}
Mystack::~Mystack()
{
delete[]input;
}
void Mystack::push(int x)
{
if (top + 1 == capacity)
{
int *vec = new int[capacity+capacity];
for (int i = 0; i <=top; i++)
{
vec[i] = input[i];
}
input = vec;
capacity = capacity * 2;
top++;
input[top] = x;
}
else
{
top++;
input[top] = x;
}
}
int Mystack::pop()
{
if (isEmpty())
{
throw std::out_of_range("Stack Underflow");
}
else
{
std::cout << "The popped element is" << input[top];
return input[top--];
}
}
bool Mystack::isEmpty() const
{
if (top == -1)
{
std::cout << "Is Empty" << std::endl;
return true;
}
else
{
std::cout << "Not Empty" << std::endl;
return false;
}
}
int Mystack::topElement() const
{
if (top == -1)
{
throw std::out_of_range("No Element to Display");
}
else
{
std::cout << "The top element is : " << input[top];
return input[top];
}
}
void Mystack::print()
{
for (int i = 0; i <= top; i++)
{
std::cout << input[i] << " ";
}
}
int main()
{
Mystack s1;
int num, ch = 1;
while (ch >0)
{
std::cout << "\n1. PUSH" << std::endl;
std::cout << "2. TOP" << std::endl;
std::cout << "3. IsEmpty" << std::endl;
std::cout << "4. POP" << std::endl;
std::cout << "5. EXIT" << std::endl;
std::cout << "6. Print" << std::endl;
std::cout << "Enter the choice" << std::endl;
std::cin >> ch; // DEBUGGER DOES NOT GIVE CONTROL TO CONSOLE WINDOW AND ASK FOR INPUT ONCE I PUT FLOAT VALUES, IT SIMPLE CROSSES IT
switch (ch)
{
case 1:
std::cout << "Enter the number to be pushed" << std::endl;
std::cin >> num;
s1.push(num);
break;
case 2:
std::cout << "Get the TOP Element" << std::endl;
try
{
s1.topElement();
}
catch (std::out_of_range &oor)
{
std::cerr << "Out of Range error:" << oor.what() << std::endl;
}
break;
case 3:
std::cout << "Check Empty" << std::endl;
s1.isEmpty();
break;
case 4:
std::cout << "POP the element" << std::endl;
try
{
s1.pop();
}
catch (const std::out_of_range &oor)
{
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
break;
case 5: exit(0);
case 6:
s1.print();
break;
default:
std::cout << "Enter a valid input";
break;
}
}
std::cin.get();
}
Once you input the int value for example as 1.1 (invalid int value). Input conversion error occurs and the input stream because of invalid data ignores the rest of the operation even the cin. Make your code more generic in order for it to handle float or double or char.

List-Search with recursion by using list library

int listRecSearch(list<int>list, const int data)
{
if (list.empty())
{
cout << "The number is not in the list, try again..." << endl;
return -1;
}
else if (list.back() == data)
{
// cout << "list.size(): " << list.size() << endl;
list.pop_back();//I needed the index begins from 0 instead of 1
return list.size();
}
else
{
// cout << "list.back(): " << list.back() << endl;
list.pop_back();
listRecSearch(list, data);
}
}
//funtion used
int main()
{
list<int>list = listGenerator(size);//generate a list with 20 random numbers.
cout << "Specify the element to be searched for: ";
cin >> data;
int position = listRecSearch(list, data);
if (position > -1)
cout << "\nFind the element at position: " << position << endl;
}
The function listRecSearch was able to display correct list.size() value and correct pop_back values. But once it returned, it always return a garbage value. I figured there were steps were still went through after return, but I can't see where and how.
There exists a code path which does not return a value. listRecSearch(list, data); should become return listRecSearch(list, data);.

Possible bug in std::unordered_map

I was trying to find the culprit behind a segfault. My debugger told be that there was no data for variable that the error was at. Every 10 seconds, there is a little script in my C++ code that runs. It does "garbage collection" and deletes some "sessions" that are probably dead.
To perform this efficiently, I use a timestamp -- when was the data last accessed. If the data is more than 10 seconds old, it is dead. There is a keepalive command that triggers every 4 seconds on the client.
To perform this GC, I loop through an std::unordered_map and substract the current time since epoch from the time stored as the value in that pair. If the time is too large, I add it to an std::vector that holds the keys to be deleted (yeah, I know it can be optimized to skip this step).
The problem that I was facing is that it loops right the first time. However, thereafter, I get a segfault, which points to the iterator value to be greater than size of the map.
Just switching back over to a standard std::map fixed the entire problem!
I shall attach the function that does all of this. All of the code is available at http://github.com/yash101/DrawingPad
Now, the code [{sourcedir}/source/Session.cxx]:
void SessionHost::cron()
{
while(true)
{
std::this_thread::sleep_for(std::chrono::seconds(10));
if(DEBUG)
{
std::cout << "Cron has started!" << std::endl;
}
while(!locky_thingy.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT)))
{}
int timethrough = 0;
std::vector<std::string> del;
for(std::map<std::string, long>::iterator ite = timestamp.begin(); ite != timestamp.end(); ++ite)
{
timethrough++;
std::cout << "Time through: " << timethrough << std::endl;
std::string curkey = ite->first;
long curval = ite->second;
std::cout << "Key: " << curkey << std::endl;
if(DEBUG)
{
std::cout << "Checking " << curkey << " with old ts of " << curval << std::endl;
}
u_int64_t curtm = std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::system_clock::now().time_since_epoch()).count();
if(DEBUG)
{
std::cout << "Current time: " << curtm << std::endl;
}
if(curtm - curval > SESSION_TIMEOUT)
{
if(DEBUG)
{
std::cout << "Deleted session handle: [" << curkey << "]" << std::endl;
}
del.push_back(curkey);
}
else
{
if(DEBUG)
{
std::cout << "Kept back session handle: [" << curkey << "]" << std::endl;
}
}
for(unsigned int i = 0; i < del.size(); i++)
{
timestamp.erase(del[i]);
data.erase(del[i]);
std::cout << "Erasing: " << del[i] << std::endl;
}
}
locky_thingy.unlock();
}
}
You have:
for(std::map<std::string, long>::iterator ite = timestamp.begin();
ite != timestamp.end(); ++ite)
{
// ...
for(unsigned int i = 0; i < del.size(); i++)
{
timestamp.erase(del[i]); // <--
// ...
}
}
In an unordered_map, erasing can invalidate iterators. So you can't erase while you're traversing - try to come up with a different algorithm. (I'm assuming some version of your question involves timestamp being an unordered_map - although there's no reference to this type in your code).
I think the error is here
for(unsigned int i = 0; i < del.size(); i++)
{
timestamp.erase(del[i]);
data.erase(del[i]);
std::cout << "Erasing: " << del[i] << std::endl;
}
} // <---------------- this is the end of the iterator loop
It should be moved up before the for loop so it doesn't invalidate.
} // <---------------- this is the end of the iterator loop
for(unsigned int i = 0; i < del.size(); i++)
{
timestamp.erase(del[i]);
data.erase(del[i]);
std::cout << "Erasing: " << del[i] << std::endl;
}
The data.erase might also have a fault if it is a vector.
If you have a vector you need to erase for you should mark the records and use
data.erase(std::remove_if(data.begin(), data.(end), CheckMark));
remove_if moves all valid data to the start of data, erase then erases from after the last valid.