I have a program that has a class, A, that I want to run in a thread. Really, it is that A is a worker and I am going to have some number of these that are running that I want to keep track of. My problem is that my current way of doing this causes a memory leak when I check it with valgrind.
#include <iostream>
#include <thread>
#include <vector>
class A {
public:
double foobar;
A() : foobar(0) { };
A(double newfoo) : foobar(newfoo) { };
void runA(double asap) {
foobar = asap;
std::cout << "foobar is now index: " << foobar << std::endl;
}
};
int main() {
std::vector<std::thread> aThreads;
for(int i = 0; i < 10; i++) {
aThreads.push_back(std::thread(&A::runA, new A(1), i));
}
for(auto& t : aThreads) {
t.join();
}
return 0;
}
So I know that the problem is the new A(100) call, and I am really not sure how to deal with this. My actual program is much bigger, and so leaks a lot more memory, so I am wondering what I can do here. I tried creating the object in the for loop, and then using std::move() to attempt to hand said object to the thread, but that failed miserably as well. I know I have to pass in the memory address, and I know that I want the distinct objects separate as they will be doing different tasks.
How do you solve the problem of leaked memory in the case where you need to create a bunch of objects to run in their own separate threads?
Make A callable directly, then pass it by value.
#include <iostream>
#include <thread>
#include <vector>
class A {
public:
double foobar;
A() : foobar(0) { };
A(double newfoo) : foobar(newfoo) { };
void operator()(double asap) {
foobar = asap;
std::cout << "foobar is now index: " << foobar << std::endl;
}
};
int main() {
std::vector<std::thread> aThreads;
for(int i = 0; i < 10; i++) {
aThreads.push_back(std::thread(A(1), i));
}
for(auto& t : aThreads) {
t.join();
}
return 0;
}
You can save all pointers to allocated objects(in a vector, for example) and then call delete on them after your join threads.
Related
I have a class foo and i put inside a member function a thread object. And i tried to initialize it like this std::thread mythread(&foo::myprint, this); inside another function. My problem is that I get the same thread::get_id with a different function foo::mycount that i need to count something. Both myprint and mycount uses this_thread::sleep_for but they don't sleep separately (something that i want to happen). I follow you up with some code example
class foo
{
void func()
{
std::thread mythread(&foo::myprint, this);
mythread.join();
}
void myprint()
{
sleep_for(1s);
cout << count << endl;
}
void mycount()
{
sleep_for(1ms);
count++;
cout << count << endl;
}
};
void main()
{
foo obj;
while(1)
{
obj.func();
obj.mycount();
}
}
I also tried putting mycount in another function with a thread object, and I don't if std::call_once affected anything, cause i used it inside the mycount function. I expected a different get_id for different functions.
Here is an example with a lambda function to start an asynchronous process.
And using std::future for synchronizing the destructor of your class with the background thread (which is counting numbers in this example).
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
// dont do "using namespace std"
using namespace std::chrono_literals;
class foo
{
public:
foo() = default;
~foo()
{
// destructor of m_future will synchronize destruction with execution of the thread (waits for it to finish)
}
void func()
{
m_future = std::async(std::launch::async, [=] { myprint(); });
}
void myprint()
{
for (std::size_t n = 0; n < 5; ++n)
{
std::this_thread::sleep_for(1s);
std::cout << n << " ";
}
std::cout << "\n";
}
private:
std::future<void> m_future;
};
int main()
{
foo obj;
obj.func(); // start thread
return 0;
}
I am currently practicing the use of multiple threads in C++. The program is simplified as follow. In this case, I have a global variable Obj, and within each task, a get function is processed by thread and thread detach will be called after.
In practice, get may take a great amount of time to run. If there are many tasks, get will be called repetitively (since each task has its own get function). I wonder if I can design a program where when one task has already obtained the data using get function and the data has been wrote to obj.text, then the rest of tasks can directly access or wait for the data from obj.text.
Can I use std::shared_ptr, std::future, std::async in c++ to implement this? If so, how to design the program? Any advice is greatly appreciated.
#include <chrono>
#include <future>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
using namespace std;
class Info {
public:
Info() { Ids = 10; };
int Ids;
std::string text;
};
Info Objs;
class Module {
public:
Module() {}
virtual void check(int &id){};
virtual void get(){};
};
class task1 : public Module {
public:
task1() { std::cout << "task1" << std::endl; }
void check(int &id) override {
thread s(&task1::get, this);
s.detach();
};
// The function will first do some other work (here, I use sleep to represent
// that) then set the value of Objs.text
void get() override {
// The task may take 2 seconds , So use text instead
std::this_thread::sleep_for(std::chrono::seconds(5));
Objs.text = "AAAA";
std::cout << Objs.text << std::endl;
};
};
class task2 : public Module {
public:
task2() { std::cout << "task2" << std::endl; }
void check(int &id) override {
thread s(&task2::get, this);
s.detach();
};
// The function will first do some other work (here, I use sleep to represent
// that) then set the value of Objs.text
void get() {
std::this_thread::sleep_for(std::chrono::seconds(5));
Objs.text = "AAAA";
std::cout << Objs.text << std::endl;
};
};
int main() {
std::vector<std::unique_ptr<Module>> modules;
modules.push_back(std::make_unique<task1>());
modules.push_back(std::make_unique<task2>());
for (auto &m : modules) {
m->check(Objs.Ids);
}
std::this_thread::sleep_for(std::chrono::seconds(12));
return 0;
}
It is a plain producer-consumer problem.
You have multiple “get()” producers. And did not implemented consumers yet.
First, you should have multiple “Info” for multithread. If there is only one Info, multithread programming is useless. I recommend “concurrent_queue”.
Second, “detach()” is not a good idea. You can’t manage child threads. You’d better use “join()”
My code sample follows. I used Visual Studio 2022
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>
#include <concurrent_queue.h>
using namespace std;
class Info {
public:
Info() { Ids = 10; };
int Ids;
std::string text;
};
concurrency::concurrent_queue<Info> Objs;
void producer()
{
while (true) {
Info obj;
std::this_thread::sleep_for(std::chrono::seconds(5));
obj.text = "AAAA\n";
Objs.push(obj);
}
}
void consumer()
{
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
Info obj;
bool got_it = Objs.try_pop(obj);
if (got_it) {
std::cout << obj.text;
}
}
}
int main() {
const int NUM_CORES = 6;
std::vector<std::thread> threads;
for (int i = 0; i < NUM_CORES / 2; ++i)
threads.emplace_back(producer);
for (int i = 0; i < NUM_CORES / 2; ++i)
threads.emplace_back(consumer);
for (auto& th : threads) th.join();
}
I was testing out boost ptr_containers and wrote a small program as below:
class Test {
public:
~Test() {
cout << "Test Destructor called" << endl;
}
};
int main(int argc, char** argv) {
boost::ptr_map<int, Test> TestContainer;
boost::ptr_vector<Test> TestVector;
for (int i=0; i<2; ++i) {
Test* ptr = new Test();
TestContainer.insert(i, ptr);
TestVector.push_back(ptr);
}
}
Once I execute the program, "Test Destructor called" is printed four time and program completes successfully. I was expecting the printing will happen 2 times and then "doube free..." error message would be thrown. Why does it not happen in the above case, but it happens with a raw pointer (Test*)?
ptr_map and ptr_vector own their elements.
The program is incorrect. Inserting the same elements in two containers at once leads to double deletion.
The behaviour of delete on an already-deleted pointer is undefined. Anything can happen. See Undefined Behaviour
Use a tool like valgrind to catch this.
In case you did want to know, easiest way to fix this sample is by using non-owning pointers for one of the containers. Be sure to manage relative lifetimes of the elements:
#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
#include <map>
class Test {
public:
~Test() {
std::cout << "Test Destructor called" << std::endl;
}
};
int main() {
boost::ptr_vector<Test> TestVector;
{
std::map<int, Test*> TestContainer;
for (int i=0; i<2; ++i) {
Test* ptr = new Test();
TestContainer.emplace(i, ptr);
TestVector.push_back(ptr);
}
}
}
I'm facing a weird issue : I can't reset (destruct and construct) properly an attribute containing a vector. It causes a segmentation fault when trying to access the vector.
Here is my code (witten in C++11). I think I simplified it the most possible to underscore the issue, but I might be wrong, sorry about that.
The goal would be to print two times two different (random) vectors. The first vector is working well, the second is completely failing for an unknown reason.
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
class A
{
std::vector<int> n;
public :
A();
std::string toString() const;
};
A::A()
{
for (int i = 0; i < 10; i++)
n.push_back(std::rand()%10);
}
std::string A::toString() const
{
for (auto i : n)
std::cout << i << ' ';
std::cout << std::endl;
}
class B
{
A a;
public :
void resetA();
A getA() const;
};
void B::resetA()
{
a = A();
}
A B::getA() const
{
return a;
}
int main()
{
srand(time(NULL));
B b;
std::cout << b.getA().toString();
b.resetA();
std::cout << b.getA().toString();
return EXIT_SUCCESS;
}
For some reason, I would like to avoid pointers and dynamic allocation as far as possible. It would fit less with my UML conception.
Moreover, this code is working well when using simple int (no vectors).
Thank you.
Your toString() doesn't return anything, so your program has Undefined Behaviour (and, in practice, returns random garbage which is most certainly not a valid std::string object).
Perhaps you wanted to use a string stream instead?
#include <sstream>
// ...
std::string A::toString() const
{
std::ostringstream s;
for (auto i : n)
s << i << ' ';
s << '\n';
return s.str();
}
Live example.
Generally, it's a good idea to compile with as many warnings turned on as possible. This would certainly have been reported as a warning then. For this particular warning (no-void function not returning anything), I strongly suggest treating it as an error.
I'm curious as to why this would crash in around 1 runs in 4.
I have a simple class that returns a string with a thread id.
This class is called from within another class asynchronously in a lambda and returns the result. The code is as simple as I can make it - I'm still learning:
class String_Returner
{
public:
string run() const
{
return "I returned from thread "+to_string(this_thread::get_id());
}
};
class Class_Holder
{
public:
Class_Holder() : number_of_runs(10)
{
srs.resize(number_of_runs);
}
void concurrent_srs()
{
for (int i = 0; i < number_of_runs; i++)
{
results.push_back(async([&]{return srs[i].run();}));
}
for (int i = 0; i < results.size(); i++)
{
cout << i << ") " << results[i].get() << endl;
}
results.clear();
}
private:
vector<future<string>> results;
vector<String_Returner> srs;
const int number_of_runs;
};
void class_b_test()
{
Class_Holder ch;
ch.concurrent_srs();
}
I realize using async with a reference is dangerous, but I figured it'd be safe if nothing is being written. I think my error probably comes from the lambda itself. This is mainly a programme to test the functionality of async and lambdas.
So my main questions:
1) Why is it crashing?
2) What better ways are there to do this?
Why is it crashing?
results.push_back(async([&]{return srs[i].run();}));
There's nothing wrong with the reference to srs in that line; as you say, it is not being modified. But the reference to i is completely meaningless; i may no longer exist when the lambda executes, and its value will be unpredictable.
But I don't understand why you feel the need to have more than one StringReturner. The class has no state, and the run method might as well be static for all the difference it makes.
What better ways are there to do this?
Do what, exactly?
If you're going to use a lambda anyway, why not just use one that directly does what you want:
#include <string>
#include <iostream>
#include <thread>
#include <future>
#include <sstream>
#include <vector>
int main() {
std::vector<std::future<std::string>> rets;
auto f = []() {
std::ostringstream b;
b << "returned from: " << std::this_thread::get_id();
return b.str();
};
for (int i=0; i<10; i++)
rets.emplace_back(std::async(f));
for (auto & t : rets) {
t.wait();
std::cout << t.get() << "\n";
}
}
Note that the thread::id type that get_id returns is guaranteed to have an operator<<, but at least as far as I know, there's no guarantee that it's a type for which std::to_string has been overloaded.