I am using boost's message queue to write a basic class with just two char arrays, but the data is not being received in the second process is empty, even though get_num_msg() returns 1 before the read and returns 0 after reading. For debugging purposes I also tried writing and reading from the same process, and that worked fine. I am using the shared pointer because earlier while just reading and writing integers, it would not read the integer at the receiver unless it was declared as shared ptr.
AccessQueue
class AccessQueue {
public:
char name[64];
char action[64];
AccessQueue(char name[64], char action[64]) {
strcpy(this->name, name);
strcpy(this->action, action);
}
AccessQueue() {}
};
sending function
// std::shared_ptr<AccessQueue> p1;
this->p1.reset(new AccessQueue("asd", "vsq"));
try {
this->mq->send(&p1, sizeof(p1), 0);
} catch(boost::interprocess::interprocess_exception & ex) {
std::cout << ex.what() << std::endl;
}
receiving function
std::cout << this->mq->get_num_msg() << "\t" << this->mq->get_max_msg_size() << "\t" << this->mq->get_max_msg() << std::endl;
AccessQueue * a;
unsigned int priority;
boost::interprocess::message_queue::size_type recvd_size;
try {
this->mq->try_receive(&a, sizeof(AccessQueue), recvd_size, priority);
} catch(boost::interprocess::interprocess_exception & ex) {
std::cout << ex.what() << std::endl;
}
std::cout << this->mq->get_num_msg() << "\t" << this->mq->get_max_msg_size() << "\t" << this->mq->get_max_msg() << std::endl;
std::cout << "It clearly maybe works " << a->action << "\t" << a->name << std::endl;
output at receiver's end:
1 128 20
0 128 20
Looks like p1 (in the sending function) is a smart pointer (like std::unique_ptr or std::shared_ptr). In that case
this->mq->send(&p1, sizeof(p1), 0);
is obviously wrong, because it puts the pointer object on the queue, instead of the data structure. Use
this->mq->send(*p1, sizeof(*p1), 0);
Or, indeed, don't use dynamic allocation in the first place:
AccessQueue packet("asd", "vsq");
mq.send(&packet, sizeof(packet), 0);
Uhoh there's more
On the receiving side, there's a similar problem:
AccessQueue * a;
// ..
mq.try_receive(&a, sizeof(AccessQueue), ...);
That receives INTO the pointer, not the object. You don't even have an object, because a (the pointer) is never initialized. Here the fix is syntactically simple:
AccessQueue a;
No more pointers. Now, a is an object and &a is the address of that object.
Note how the original was UB because you read sizeof(AccessQueue) bytes into a pointer. However the pointer is only 8 bytes and the struct is 128 bytes. Ooops!
Simplified Working Demo
This works:
Live On Wandbox¹
#include <boost/interprocess/ipc/message_queue.hpp>
#include <iostream>
#include <iomanip>
namespace bip = boost::interprocess;
using MQ = bip::message_queue;
template<size_t N>
static inline void safe_copy(std::array<char, N>& dst, std::string_view src) {
std::copy_n(src.data(), std::min(src.size(), N), dst.data());
dst.back() = 0; // make sure of NUL termination
}
struct AccessQueue {
std::array<char, 64> name{0};
std::array<char, 64> action{0};
AccessQueue(std::string_view n = "", std::string_view a = "") {
safe_copy(name, n);
safe_copy(action, a);
}
};
static_assert(std::is_standard_layout_v<AccessQueue>);
struct X {
void send() {
AccessQueue packet("asd", "vsq");
try {
mq.send(&packet, sizeof(packet), 0);
} catch(std::exception const & ex) {
std::cout << ex.what() << std::endl;
}
}
AccessQueue receive() {
AccessQueue retval;
report();
try {
unsigned int priority;
MQ::size_type recvd_size;
mq.try_receive(&retval, sizeof(AccessQueue), recvd_size, priority);
} catch(std::exception const & ex) {
std::cout << ex.what() << std::endl;
}
report();
return retval;
}
void report() {
std::cout << mq.get_num_msg() << "\t" << mq.get_max_msg_size() << "\t" << mq.get_max_msg() << std::endl;
}
MQ mq { bip::open_or_create, "somequeue", 10, sizeof(AccessQueue) };
};
int main() {
X tryit;
tryit.send();
auto const& [name, action] = tryit.receive();
std::cout << std::quoted(name.data()) << " " << std::quoted(action.data()) << std::endl;
}
Prints
1 128 10
0 128 10
"asd" "vsq"
Note
using std::array over C arrays gives you copy semantics by default
guard the POD-ness of AccessQueue
make sure the members are initialized
make sure the copies are safe
make sure the copies are NUL-terminated always
Don't use new or delete. Why should C++ programmers minimize use of 'new'?
make sure your receive buffer size matches the max_msg_size (boost interprocess message_queue and fork)
¹ shared emmory is prohibited on Wandbox :(
Related
In question about scope of exception it is stated by Aj. that throw and catch clauses will create copies of the exception (unless reference is used I guess)
I tried myself a small toy code and I don't understand the result. here :
//g++ 7.4.0
#include <iostream>
using namespace std;
struct Some_error {
Some_error(float code):err_code(code){ cout << "Some_error(" << err_code << ")\n"; }
~Some_error() { cout << "~Some_error(" << err_code << ")\n"; }
Some_error(const Some_error& o):err_code(o.err_code+0.1) { cout << "Some_error(copy::" << err_code << ")\n"; }
Some_error(Some_error&& o):err_code(std::move(o.err_code)+.01){ cout << "Some_error(move::" << err_code << ")\n"; }
int get_code() const { return err_code; }
private : float err_code;
};
int do_task() {
if ( false ) return 42; else throw Some_error {1};
cout << "end do_task\n" ;
}
void taskmaster(){
try { auto result = do_task(); cout << "the answer is " << result << "\n" ; }
catch (Some_error e) { cout << "catch Some_error : " << e.get_code() << "\n" ; }
cout << "end taskmaster\n" ;
}
int main() { taskmaster(); }
the trace I get is as follows :
Some_error(1)
Some_error(copy::1.1)
catch Some_error : 1
~Some_error(1.1)
~Some_error(1)
end taskmaster
Now first, as I used no reference here, according to Aj., I would expect 2 copies to happen.
And second, there was a copy, that set err_code to 1.1, but the display is still 1.
Remark: just to be complete, I changed the catch to : catch(Some_error& e),
and then the trace looks fine to me :
Some_error(1)
catch Some_error : 1
~Some_error(1)
end taskmaster
I would expect 2 copies to happen.
Why? Only one copy is made by the catch block. Where would the second copy happen?
set err_code to 1.1, but the display is still 1.
Because get_code returns an int, so the floating point value gets truncated.
Now I need to detect whether my class is created as a stack/global/thread_local variable, for example:
class Foo {
public:
Foo() {
if(im_on_stack) {
std::cout << "I'm on stack" << std::endl;
} else if(im_in_global) {
std::cout << "I'm in global" << std::endl;
} else if(im_a_thread_local) {
std::cout << "I'm a thread_local" << std::endl;
} else {
std::cout << "I'm on ohters location" << std::endl;
}
}
};
class Bar {
Foo mFoo;
};
Foo gFoo;
thread_local Foo tFoo;
int main() {
Foo lFoo;
}
and the out put should be:
I'm on ohters location
I'm in global
I'm a thread_local
I'm on stack
This there any way in C++ I can do this?
Edit:
why I'm doing this:
I'm writing a garbage collection library, and I got a class, let's call it gc_ptr, I need to know if this gc_ptr is a gc root (which is create on the location I mentioned) or not (which is a member of another class)
Edit2:
According to the concept of gc root, which is a reference which is not on a heap, I should probably asked in this way: can I detect if my class is create on the heap? But I think on heap or on stack make this question no difference.
Short answer: No. Not with standard C++. There may be compiler or OS specific solutions, but nothing portable.
I guess you could make a heuristic to detect stack allocated objects by detecting in their constructor whether their address is close to a stack allocated variable. Assuming that the stack and the heap have completely different memory addresses it should work. Completely undefined behaviour though according to the standard. e.g.:
#include <iostream>
#include <memory>
struct A
{
A()
{
int test = 0; // test is on the stack
auto distance = reinterpret_cast<char*>(this) - reinterpret_cast<char*>(&test);
isStack = std::abs(distance) < 1024; // completely arbitrary magic number, will need to experiment
}
bool isStack;
};
int main()
{
std::cout << "stack: " << A().isStack << "\n";
std::cout << "stack: " << std::make_unique<A>()->isStack << "\n";
}
I don't think you could expand this technique to thread local variables. You'd also need to take care in copy constructors and assignment operators to handle copying from a stack to a heap object and vice versa.
This is not part of the spec, so no.
If you told us on what system/os you are working, maybe we can assist - some systems may provide the stack address and size - usually this is available in embedded devices as part of the compiler output (the address), and as input (the size) as part of the environment/project configuration.
What I wrote in my comment:
Can be done to some extent: Assuming, you need it only for a certain kind of classes: You have to overload new (or wrap dynamic construction in a static create). You have to derive all considered classes from a base class with a specific constructor. To pass info from new to the constructor is a bit tricky. In our case, we used a global set where new remembered pointers to created instances and the corresponding constructor looked into it to determine whether creation was done by new. That was sufficient for us. (About the other topics - no idea...)
A demo:
#include <iostream>
#include <set>
class Object {
private:
static thread_local std::set<void*> pNewSet;
bool _isNewed;
public:
Object();
Object(const Object&) = delete;
const Object& operator=(const Object&) = delete;
~Object() = default;
static void* operator new(size_t size);
bool isNewed() const { return _isNewed; }
private:
static std::set<void*>& getNewPtrs()
{
static thread_local std::set<void*> pNewSet;
return pNewSet;
}
};
void* Object::operator new(size_t size)
{
std::set<void*> &pNewSet = getNewPtrs();
void *p = ::operator new(size);
if (p) pNewSet.insert(p);
return p;
}
Object::Object(): _isNewed(false)
{
std::set<void*> &pNewSet = getNewPtrs();
std::set<void*>::iterator iter = pNewSet.find((void*)this);
if (iter != pNewSet.end()) {
_isNewed = true;
pNewSet.erase(iter);
}
}
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
// a global static instance
static Object o;
int main()
{
DEBUG(std::cout << o.isNewed() << '\n');
// a static instance (local scope)
DEBUG(static Object o1);
DEBUG(std::cout << o1.isNewed() << '\n');
// a local instance
DEBUG(Object o2);
DEBUG(std::cout << o2.isNewed() << '\n');
// as members
DEBUG(struct Composed { Object o1, o2; } comp);
DEBUG(std::cout << comp.o1.isNewed() << ' ' << comp.o2.isNewed() << '\n');
// created with new
DEBUG(Object *pO = new Object());
DEBUG(std::cout << pO->isNewed() << '\n');
DEBUG(delete pO);
// created as members in an object created with new
DEBUG(Composed *pComp = new Composed());
DEBUG(std::cout << pComp->o1.isNewed() << ' ' << pComp->o2.isNewed() << '\n');
DEBUG(delete pComp);
}
Output:
std::cout << o.isNewed() << '\n';
0
static Object o1;
std::cout << o1.isNewed() << '\n';
0
Object o2;
std::cout << o2.isNewed() << '\n';
0
struct Composed { Object o1, o2; } comp;
std::cout << comp.o1.isNewed() << ' ' << comp.o2.isNewed() << '\n';
0 0
Object *pO = new Object();
std::cout << pO->isNewed() << '\n';
1
delete pO;
Composed *pComp = new Composed();
std::cout << pComp->o1.isNewed() << ' ' << pComp->o2.isNewed() << '\n';
0 0
delete pComp;
Live Demo on Compiler Explorer
Notes:
The copy constructor and assignment operator of Object are deleted intenionally.
Derived classes may provide a copy constructor but it has to call Object::Object().
The sample doesn't consider other flavors of new (e.g. operator new[] or the align variants since C++17). That should be done in productive code.
No, but you can prevent creation of objects on heap/stack.
To prevent creation on stack make the destructor private/protected:
class heap_only
{
public:
void release() const { delete this; }
protected:
~heap_only() {}
};
struct heap_only_deleter
{
void operator()( heap_only* p ) { p->release(); }
};
using up_heap_only = std::unique_ptr<heap_only, heap_only_deleter>;
//...
heap_only ho; // fails
heap_only* pho = new heap_only();
pho->release();
up_heap_only up{ new heap_only() };
To prevent creation on heap make the new operators private/protected:
class stack_only
{
protected:
static void* operator new( std::size_t );
static void* operator new[]( std::size_t );
};
//...
stack_only* pso = new stack_only(); // fails
stack_only so;
Regarding your edits, and just for fun:
void* pstart;
bool is_on_stack( void* p )
{
int end;
return pstart >= p && p > &end;
}
int globalint;
int main()
{
//
int start;
pstart = &start;
//
int stackint;
std::cout << std::boolalpha
<< is_on_stack( &globalint ) << std::endl
<< is_on_stack( &stackint ) << std::endl
<< is_on_stack( new int );
//...
}
I use ESP-32 and need to pass std::shared_ptr using FreeRTOS queue. However, it loose one link. I think that this is source of a problem:
#include <iostream>
#include <memory>
#define PRINT_USE_COUNT(p) std::cout << "Use count: " << p.use_count() << std::endl;
extern "C" {
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>
}
class testClass {
public:
testClass() {
std::cout << "Class is constructed" << std::endl;
};
virtual ~testClass() {
std::cout << "Class is destructed" << std::endl;
};
};
struct container {
std::shared_ptr<testClass> field;
};
extern "C" void app_main(void) {
auto queue = xQueueCreate(1, sizeof(container));
auto p = std::make_shared<testClass>();
PRINT_USE_COUNT(p); // 1
{
container c;
c.field = p;
PRINT_USE_COUNT(p); // 2
xQueueSendToBack(queue, &c, 0);
PRINT_USE_COUNT(p); // 2
}
PRINT_USE_COUNT(p); // 1 (Ooops!)
{
container c;
assert(xQueueReceive(queue, &c, 0) == pdTRUE);
PRINT_USE_COUNT(c.field); // 1
}
// Class is destructed
std::cout << "Test finished" << std::endl;
vQueueDelete(queue);
}
So there is a pointer in queue, but it isn't counted!
How can I solve this issue (and keep using FreeRTOS queue if possible)? Using std::move doesn't help.
A C-style queue of raw pointers will only works for C++ shared_ptr iff std::is_trivial<T>::value is true (mainly POD or trivially copyable object).
Since there are memcpy and other plain C operation manipulating memory the reference count will not be handled properly (because it is C-code behind the scene and it does not call destructor among other thing) and you could end up with a memory leak.
There is no easy way to circumvent this, but the best way is to manage the memory yourself.
See this question also : Shared pointers and queues in FreeRTOS
I managed to transform unique pointer into a raw format which could be sent via a message queue.
See here: https://codereview.stackexchange.com/questions/241886/using-unique-ptr-in-freertos.
Please note I posted it in code review because I am not sure whether there are really no memory leaks or this can be implemented much more cleanly.
I will test whether I can actually use this for the IPC in our project.
I don't always agree that developing something from scratch is best option. Using something that is well tested might be best option in most occasions even-though it could require some tweaking for making it fit to your needs.
With the queue you can pass a dynamically created instance of your container. It is very rare, if it is at all, to use a queue for sending data from one task to same task, as the example above. I don't like pretty much working with dynamic allocations in embedded CPUs, the overhead can sometimes impact performance too much.
Here below is a working PoC where, instead of a raw copy, a pointer to a new container instance is passed. In this approach it is the responsibility of the receiving task to release the instance to avoid memory leaks.
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
}
#include <iostream>
#include <memory>
#define PRINT_USE_COUNT(p) std::cout << "Use count: " << p.use_count() << std::endl;
class testClass {
public:
testClass() {
std::cout << "testClass constructed" << std::endl;
}
~testClass() {
std::cout << "testClass destructed" << std::endl;
}
};
class myContainer {
public:
myContainer(std::shared_ptr<testClass> p) {
_p = p;
std::cout << "myContainer constructed" << std::endl;
}
~myContainer() {
std::cout << "myContainer destructed" << std::endl;
}
std::shared_ptr<testClass>& p() {
return _p;
}
private:
std::shared_ptr<testClass> _p;
};
extern "C" void app_main(void) {
std::cout << "Start of test, creating the shared_ptr..." << std::endl;
auto p = std::make_shared<testClass>();
PRINT_USE_COUNT(p);
std::cout << "Creating one container..." << std::endl;
myContainer c(p);
PRINT_USE_COUNT(p);
std::cout << "Creating the queue..." << std::endl;
auto q = xQueueCreate(1, sizeof(myContainer*));
std::cout << "Sending a dynamically created item to the queue..."
<< std::endl;
myContainer *cp = new myContainer(p);
xQueueSendToBack(q, &cp, 0);
PRINT_USE_COUNT(p);
{
myContainer *pc;
xQueueReceive(q, &pc, 0);
PRINT_USE_COUNT(p);
std::cout << "Use count of pc->p() " << pc->p().use_count()
<< std::endl;
std::cout << "Freeing the dynamically created item..." << std::endl;
delete pc;
PRINT_USE_COUNT(p);
}
std::cout << "end of test" << std::endl;
}
Here's the program's output:
Start of test, creating the shared_ptr...
testClass constructed
Use count: 1
Creating one container...
myContainer constructed
Use count: 2
Creating the queue...
Sending a dynamically created item to the queue...
myContainer constructed
Use count: 3
Use count: 3
Use count of pc->p() 3
Freeing the dynamically created item...
myContainer destructed
Use count: 2
end of test
myContainer destructed
testClass destructed
I have 2 structures in one DataStorage structure. What I want in the end is to have possiblity to use first structure independently and also to be able to save DataStorage and to be sure that first two are going to be saved. This may not be relevant, because the question is - is this code safe?
Please take a look at code, it ilustrates all much better.
I believe my approach is OK, but my fear has ever since been to use pointers and references because of memory leaks and other unexpected behaviours.
#include < iostream >
#include < string >
//---------------------------
//two structures to hold some data
//and a structure to hold 2 structures
struct settings_t {
uint8_t myBaseID = 68;
uint8_t reserved1;
} settingsD;
struct values_t {
unsigned long longValue0;
};
//struct in question, will also later be passed to template class like
//some_template_type <DataStorage>save;
struct DataStorage {
settings_t & settings = settingsD;
values_t valueStore;
};
//--------------------------
//function that generates new structure
settings_t generateNew() {
settings_t ret;
ret.myBaseID = 66;
return ret;
}
//new test instance of datastorage
void test1() {
DataStorage ds1;
std::cout << "Hello, " << ds1.settings.myBaseID << "!\n";
}
int main() {
DataStorage ds;
ds.settings.myBaseID = 65;
std::cout << "Hello, " << ds.settings.myBaseID << "!\n";
std::cout << "Hello, " << settingsD.myBaseID << "!\n";
test1();
ds.settings = generateNew();
std::cout << "Hello, " << ds.settings.myBaseID << "!\n";
std::cout << "Hello, " << settingsD.myBaseID << "!\n";
test1();
}
And the result is (as desired):
Hello, A!
Hello, A!
Hello, A!
Hello, B!
Hello, B!
Hello, B!
I was debugging some code involving pointers to member fields, and i decided to print them out to see their values. I had a function returning a pointer to member:
#include <stdio.h>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
switch (what) {
case 0: return &test::x;
case 1: return &test::y;
case 2: return &test::z;
default: return NULL;
}
}
I tried using cout:
#include <iostream>
int main()
{
std::cout << select(0) << " and " << select(3) << '\n';
}
I got 1 and 0. I thought the numbers indicated the position of the field inside the struct (that is, 1 is y and 0 is x), but no, the printed value is actually 1 for non-null pointer and 0 for null pointer. I guess this is a standard-compliant behavior (even though it's not helpful) - am i right? In addition, is it possible for a compliant c++ implementation to print always 0 for pointers-to-members? Or even an empty string?
And, finally, how can i print a pointer-to-member in a meaningful manner? I came up with two ugly ways:
printf("%d and %d\n", select(0), select(3)); // not 64-bit-compatible, i guess?
ptr_to_member temp1 = select(0); // have to declare temporary variables
ptr_to_member temp2 = select(3);
std::cout << *(int*)&temp1 << " and " << *(int*)&temp2 << '\n'; // UGLY!
Any better ways?
Pointers to members are not as simple as you may think. Their size changes from compiler to compiler and from class to class depending on whether the class has virtual methods or not and whether it has multiple inheritance or not. Assuming they are int sized is not the right way to go. What you can do is print them in hexadecimal:
void dumpByte(char i_byte)
{
std::cout << std::hex << static_cast<int>((i_byte & 0xf0) >> 4);
std::cout << std::hex << static_cast<int>(i_byte & 0x0f));
} // ()
template <typename T>
void dumpStuff(T* i_pStuff)
{
const char* pStuff = reinterpret_cast<const char*>(i_pStuff);
size_t size = sizeof(T);
while (size)
{
dumpByte(*pStuff);
++pStuff;
--size;
} // while
} // ()
However, I'm not sure how useful that information will be to you since you don't know what is the structure of the pointers and what each byte (or several bytes) mean.
Member pointers aren't ordinary pointers. The overloads you expect for << aren't in fact there.
If you don't mind some type punning, you can hack something up to print the actual values:
int main()
{
ptr_to_member a = select(0), b = select(1);
std::cout << *reinterpret_cast<uint32_t*>(&a) << " and "
<< *reinterpret_cast<uint32_t*>(&b) << " and "
<< sizeof(ptr_to_member) << '\n';
}
You can display the raw values of these pointer-to-members as follows:
#include <iostream>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
switch (what) {
case 0: return &test::x;
case 1: return &test::y;
case 2: return &test::z;
default: return NULL;
}
}
int main()
{
ptr_to_member x = select(0) ;
ptr_to_member y = select(1) ;
ptr_to_member z = select(2) ;
std::cout << *(void**)&x << ", " << *(void**)&y << ", " << *(void**)&z << std::endl ;
}
You get warnings about breaking strict anti-aliasing rules (see this link), but the result is what you might expect:
0, 0x4, 0x8
Nevertheless, the compiler is free to implement pointer-to-member functionality however it likes, so you can't rely on these values being meaningful.
I think you should use printf to solve this problen
#include <stdio.h>
struct test{int x,y,z;}
int main(int argc, char* argv[])
{
printf("&test::x=%p\n", &test::x);
printf("&test::y=%p\n", &test::y);
printf("&test::z=%p\n", &test::z);
return 0;
}