Using a big struct as parameter with std async causes bug - c++

I have a big struct that needs to be processed. So I use std async to do it on another thread. Here is a simple example below:
#include <iostream>
#include <future>
using namespace std;
struct teststruct{
float thisvalue[32][32][64];
};
void foo(teststruct thisdummy) {
this_thread::sleep_for(chrono::milliseconds(234));
cout << "hello";
}
int main() {
teststruct thisteststruct;
foo(thisteststruct); // this does work
auto futurevalue = async(launch::async, foo, thisteststruct); //this doesnt work
return 0;
}
I have a struct that is just a big 3d array of floats. When I run this I get an error saying Bus error: 10. Just calling foo without using async works but using std async it doesn't work. Somehow it is related with the struct size since when I make the struct
struct teststruct{
float thisvalue[32][32][63];
};
it magically works. I have tried splitting up the struct by half so a 32x32x32 array instead of a 32x32x64 array and taking in teststructs as parameters but it doesn't work. As I said above I think this has to do with the size of the struct. How can I fix this?

You are probably blowing the stack.
sizeof(teststruct) is 32*32*64*sizeof(float). Assuming a 4-byte float, that's 256KB that you are attempting to pass by value into foo.
While there are flags you can pass to the compiler to increase stack size, you really want to avoid passing large objects by value. As that requires an in-memory copy to be made. Pass that big struct by shared_pointer. That will enable it to be passed around on the main thread and on the async thread without using any significant amount of stack memory. It's also faster since it avoids the large copy of that object.
#include <iostream>
#include <future>
#include <memory>
using namespace std;
struct teststruct{
float thisvalue[32][32][64];
};
void foo(shared_ptr<teststruct> thisdummy) {
this_thread::sleep_for(chrono::milliseconds(234));
cout << "hello";
}
int main() {
auto thisteststruct = make_shared<teststruct>();
foo(thisteststruct);
auto futurevalue = async(launch::async, foo, thisteststruct);
return 0;
}

Making it a pointer or reference should do the trick.
(untested)
void foo(teststruct *thisdummy) {
this_thread::sleep_for(chrono::milliseconds(234));
cout << "hello";
}
int main() {
teststruct thisteststruct;
foo(&thisteststruct); // this does work
auto futurevalue = async(launch::async, foo, &thisteststruct); //this doesnt work
futurevalue.get();
return 0;
}
What the below discussion is about is:
If the std::future obtained from std::async is not moved from or bound
to a reference, the destructor of the std::future will block at the
end of the full expression until the asynchronous operation completes,
essentially making code such as the following synchronous:
See this

Related

How can I declare a stack reference in C++11?

I am implementing a stack reference. However I got the error of 'Segmentation fault (core dumped)'. I am using g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2 on Ubuntu 14.04. Many thanks.
The code is listed below.
#include<iostream>
#include<stack>
using namespace std;
int main() {
stack<int>* S;
S->push(4);
return 0;
}
Stop using new wherever you can.
#include <iostream>
#include <stack>
int main() {
std::stack<int> s;
s.push(4);
return 0;
}
Having "naked" pointers representing object ownership is generally discouraged, as it is error-prone. Either use automatic variables, or the smart pointers provided by the library.
#include <stack>
#include <memory>
int main()
{
// On the stack, local scope. This is the fastest;
// unlike Java we don't have to "new" everything.
std::stack<int> s1;
s1.push(4);
// Dynamically allocated, gets auto-deleted when the
// last copy of the smartpointer goes out of scope.
// Has some overhead, but not much.
// Requires some extra plumbing if used on arrays.
auto s2 = std::make_shared<std::stack<int>>();
auto s2_copy(s2); // can be copied
s2->push(4);
// Dynamically allocated, gets auto-deleted when the
// smartpointer goes out of scope. No overhead, but
// cannot be copied / shared.
// Works out-of-the-box with arrays as well.
auto s3 = std::make_unique<std::stack<int>>();
s3->push(4);
}
you have to create the object then you can point to it.
#include<iostream>
#include<stack>
using namespace std;
int main() {
stack<int> s;
stack<int>& S = s;
S.push(4);
return 0;
}

C++ Dynamic Array Member Variable Assignment

I am having a problem with assigning new values to a dynamic int array that is a data member variable of the class IntersectionFlowRate(). I can initialize and print the values of the array inside the constructor. However, when I exit the constructor to the another class and then later call a function within the IntersectionFlowRate() class passing in variables to overwrite the initial values of the data member it will segmentation fault. I have debugged to find that overwriting the array is causing the seg fault. And that even attempting to access the dynamic array within one of its functions will seg fault.
My question is how can I edit the values of a dynamic int array member variable from within one of its functions i.e setArrayElement(int index, int x).
Here is some of my code. Sorry if I am unclear or missing something ridiculous. I have been stuck on this for hours.
#ifndef INTERSECTIONFLOWRATE_H
#define INTERSECTIONFLOWRATE_H
class IntersectionFlowRate
{
public:
IntersectionFlowRate();
~IntersectionFlowRate();
void setFlowCycle(int index, int flow);
private:
int* m_flowRateMotorCycle;
};
#endif
in the .h file ^
#include "IntersectionFlowRate.h"
#include <cstdlib>
#include <iostream>
#include <new>
using namespace std;
IntersectionFlowRate::IntersectionFlowRate()
{
const int SIZE = 4; //Constant for m_flowRates[] size
//DYNAMIC MEMORY DELETE LATER
m_flowRateMotorCycle = new int[SIZE];
for(int i = 0; i < SIZE; i++){
m_flowRateMotorCycle[i] = 0;
cout << m_flowRateMotorCycle[i] << endl;
cout << "WE GOT HERE" << endl;
}
}
void IntersectionFlowRate::setFlowCycle(int index, int flow){
cout << "INDEX: " << index << endl;
cout << "FLOW: " << flow << endl;
m_flowRateMotorCycle[index] = flow; //seg fault is here
}
I have another class that creates a pointer to a IntersectionFlowRate() object and then calls its setFlowCycle function passing in two VALID ints. With the debugging I was able pass 0 and 3 to the function setFlowCycle(0, 3) just fine and output those variables within the function.
#ifndef TRAFFICSIM_H
#define TRAFFICSIM_H
#include "IntersectionFlowRate.h"
using namespace std;
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
~TrafficSim(); //Destructor
private:
IntersectionFlowRate* m_flowRate;
};
#endif
#include "TrafficSim.h"
#include "IntersectionFlowRate.h"
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
I replicated the error with this code. If no one else can I am completely unsure of what is possibly wrong anymore.
You are setting a local variable called m_flowRate, not the member variable m_flowRate of your TrafficSim class:
Instead of this:
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
It should be this:
TrafficSim::TrafficSim()
{
m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
But overall, it not need be a pointer. It could be an object member within your class. That would cut down on the pointer usage a bit:
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
private:
IntersectionFlowRate m_flowRate;
};
Then:
TrafficSim::TrafficSim()
{
m_flowRate.setFlowCycle(0, 3);
}
As to your question as to how to incorporate usage of std::vector in your class, here is a code sample of the IntersectionFlowRate class, rewritten using vector:
Vector sample
Also, another source of problems is that your classes fail to follow the Rule of 3 when you have pointers to dynamically allocated memory in your class.
Using std::vector takes care of this automatically, but if you insist on using pointers, you need to adhere to the directions at the link posted.
Yes, use a std::vector, it is much simpler, and it is a template so it also pretty fast and works any type (best for primitive types or pointers to objects) , and it also has boundary checking and other useful things.
If you need fast array-like access then you could use std::map which associates a key with a value, like so
std::map<UINT, YourClass*> m_mapIDs_to_YourClass;
When you first start using stl containers they might seem a little strange, but after a short while you cannot do without them, luckily they have been part of the C++ standard for some time now.
Boundary check for both these containers can be done by comparing your iterator to mapYourMap.end(), if they are equal you have passed the last element and trying to access data through the iterator will cause an exception.
Example for std::vector (if vecInt is a vector< int >):
vector<int>::iterator it = vecInt.begind();
if (it == vecInt.end()) return; // vector is empty
do { // runs through elememts until out of bound, useful for searching
i++
while (it != vecInt.end());

How can I call this function in main

// pointer to functions
#include <iostream>
#include <vector>
using namespace std;
struct boo{
string u;
int p;
};
vector <boo> om(boo &bo){
cin >> bo.u;
cout << bo.u;
}
int main(){
string q;
vector <boo> b;
om(b);
}
Ok I need to understand how will I be able to write vector<boo> om(boo &bo) into my main(). I always get some type of error with it and I need help with it. I can't ever call the function into main because I just simply don't know how to call it into main. Well I know how to call om([I just need help with this part]) I have no idea what to fill this in with.
P.S
Sorry this is at the bottom Im a noob with stackoverflow.
Taking a shot in the dark here because this seems to be the most likely intent. If i'm wrong, hopefully it is still instructional.
#include <iostream>
#include <vector>
I removed the using namespace std that was here because it's dangerous. Don't believe me? Do a quick search. StackOverflow is littered with "WTF is going on?" questions that resolve down to "something in the std namespace had the same name as your variable."
struct boo
{
std::string u;
int p;
};
I've left Boo alone to keep it recognizable to the OP. However, descriptive names really help your code explain itself. No one here, excluding the OP, has any clue what a boo represents and how it should be used or what it's members represent and how they should be used. This limits the our ability to assist the OP with debugging support and advice.
On to function om. Again, terrible name. A function name should provide some hints as to what the function does.
Assumptions:
Om is intended to
read in input to get the data required to fill out a boo structure
place that boo structure into main's vector b
With that in mind,
No need to return anything except perhaps an error code if the user fails to enter correct input.
The only thing worth passing in is a reference to the vector. The reference allows the vector supplied by the caller to be modified.
If we knew what a boo was someone might be able to suggest better ways to do this and validate the user input.
void om(std::vector<boo> &bo)
{
boo temp; //start by making a temporary boo
std::cin >> temp.u; // read user input into the temporary boo
// removed the print out here
bo.push_back(temp); // copy the temporary boo into the vector
}
main is altered to remove unused string q and output the contents of vector b
int main()
{
std::vector<boo> b; // usual nagging about non-descriptive name
om(b);
for (boo testboo: b)
{ // print all boos in b
std::cout << testboo.u << std::endl;
}
}
And as one cut-n-paste-able block for trying it out and playing around:
#include <iostream>
#include <vector>
struct boo
{
std::string u;
int p;
};
void om(std::vector<boo> &bo)
{
boo temp; //start by making a temporary boo
std::cin >> temp.u; // read user input into the temporary boo
// removed the print out here
bo.push_back(temp); // copy the temporary boo into the vector
}
int main()
{
std::vector<boo> b; // usual nagging about non-descriptive name
om(b);
for (boo testboo: b)
{ // print all boos in b
std::cout << testboo.u << std::endl;
}
}

Passing pointer to dynamically allocated array by copy to function has unexpected result

I was just messing around with passing pointers to functions to wrap my head around how it works and I came across some behavior that was unexpected. I have the following code:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cmath>
#include <iomanip>
using namespace std;
struct t
{
string x;
string y;
};
void foo(t*);
int main()
{
t* ts = new t[2];
ts[0].x = "t1.x";
ts[0].y = "t1.y";
ts[1].x = "t2.x";
ts[1].y = "t2.y";
foo(ts);
cout << ts[0].x << endl;
}
void foo(t* s)
{
delete[] s;
s = new t[2];
s[0].x = "FOO.X";
s[1].y = "FOO.Y";
}
The output here, interestingly enough, is "FOO.X". I expected that since inside of foo, s is a copy of the pointer ts that when I delete[] s I effectively delete[] ts as they both point to the same address. Then s = new t[2]; should have no effect on ts. After foo returns, I should no longer have access to s or the array it points to and ts should point to who knows where. Am I missing somehthing?
Note: This is just a test project that I made where I constantly write and erase blocks of code to test different concepts. All the includes and using namespace std is for ease of use, and it is NOT code that I am writing for any sort of practical use, purely educational. Also, I am using MS VS 2013.
Try changing your foo() like this and see the result:
void foo(t* s)
{
delete[] s;
// Additional memory allocation
t* u = new t[2];
s = new t[2];
s[0].x = "FOO.X";
s[1].y = "FOO.Y";
}
By adding another memory allocation, I moved s to another location in the memory, which is not anymore overlapping with ts. Otherwise, s was simply allocated at the same location where ts previously resided.
As pointed out in the comments, you are observing an undefined behavior, which you should by no means rely on. The example above illustrates that pretty well.

Issue with struct constructor causing stack overflow

Both sections of code below are drastically simplified, isolated versions of my actual code. The examples are just big enough to reproduce the problem. The first section of code below works fine. The section section is an attempt to begin to make it part of a class. I'm trying to take tiny steps since small modifications to something like the struct shown below require lots of changes throughout the code which is full of pointers, pointer to pointers and references which all involve this struct. Can you tell me why the second section of code throws a stack overflow within it's constructor and what small changes can be made to fix it?
Working code:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
const int maxSize = 3;
struct Item{
int count;
Item *items[maxSize + 1];
};
void foo()
{
Item *p;
p = new Item();
p->count = 2;
cout << p->count << endl;
}
int main(int argc, char *argv[])
{
foo();
return 0;
}
Attempt to very gradually modify the code as a whole toward becoming a class:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
int maxSize = 3;
struct Item{
int count;
Item *items;
Item()
{
items = new Item[maxSize + 1]; // stack overflow
}
};
void Initialize(int size)
{
maxSize = size;
}
void foo()
{
Item *p;
p = new Item();
p->count = 2;
cout << p->count << endl;
}
int main(int argc, char *argv[])
{
Initialize(5);
foo();
return 0;
}
The first call to construct a Item calls new Item[maxSize+1], which calls the default constructor, which calls new Item[maxSize+1], which calls the default construct, and so on until you reach stack overflow.
All the answers are right. I want to suggest a solution for you:
Instead of initializing the array within the ctor, you could implement an initialization method like
init(int maxSize) {
items = new Item[maxSize + 1];
}
that you can call after having constructed the object. This should avoid the stack overflow. In general, you should avoid to place instances of an object inside the object itself. Its better to use Collections of the Item
List<Item>, std::vector<Item>, ...
It is because in working version you have reference to an array of object, but not actual object of Items. In second version, you are creating objects by using keyword new. So, in second version in constructor it will call itself! It will call it's own constructor infinite times. Hence, you see runtime exception stackoverflow :)
Above posters are right. Within the constructor of Item you create items (by creating an array). So the ctor is again called, which creates more items, which .... This is more or less an infinite loop which eats up your stack.
Either stick with the references or use a collection like List - so you can add the items later on dynamically.