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!
Related
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 :(
I am looking for better solutions on how to organize and access my data.
My data is a set of structures (_array_10 and _array_20 in the example below) that contain std::array of different sizes (see my_data below).
Ideally, I would like to access it as it was an array of structs with different lengths, but this is not allowed, since different lengths are different types.
The solution I have below works, but I find it extremely ugly (specially the array of void *).
Q1. Any ideas on how to have a safer, more efficient/portable, or at least less ugly solution?
Q2. Is the proposed solution without templates portable? It relies on the fact that the length is stored before the rest of the data, since casting the pointer to an object with wrong length would mess the access to all fields that come after the first field of variable length.
My limitations include:
C++11
standard libraries
no std::vector
memory usage prevents me from being able to simply allocate an array of my_data with the maximum possible length
the bulk of the data (_array_10, _array_20, etc) will be placed in a memory area reserved specially for it
Using data_view and template require knowledge of the length of the arrays in build time. It would be great if we could avoid it.
Question edited to include the solution proposed by Guillaume Racicot
#include <iostream>
#include <array>
std::array<void *, 2> _ptrs;
template <int length>
struct my_data
{
int array_length;
std::array<int, length> something;
std::array<int, length> data;
my_data()
{
array_length = length;
}
};
struct my_data_view
{
int array_length;
const int * something;
const int * data;
template <int length>
my_data_view(my_data<length> const & data_in) :
array_length(length),
something(data_in.something.data()),
data(data_in.data.data())
{}
};
template <int length>
void
print_element(int array_idx, int element)
{
my_data<length> * ptr = reinterpret_cast<my_data<length> *>(_ptrs[array_idx]);
std::cout << "array " << length << ", data[" << element << "] = " << ptr->data[element] << ".\n";
}
void
print_element(int array_idx, int element)
{
my_data<1> * ptr = reinterpret_cast<my_data<1> *>(_ptrs[array_idx]);
int length = ptr->array_length;
int data_to_print = 0;
switch (length)
{
case 10:
{
data_to_print = reinterpret_cast<my_data<10> *>(_ptrs[array_idx])->data[element];
break;
}
case 20:
{
data_to_print = reinterpret_cast<my_data<20> *>(_ptrs[array_idx])->data[element];
break;
}
}
std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
}
void
print_element(my_data_view view, int element)
{
int length = view.array_length;
int data_to_print = view.data[element];
std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
}
int
main()
{
my_data<10> _array_10;
my_data<20> _array_20;
_ptrs[0] = static_cast<void *>(&_array_10);
_ptrs[1] = static_cast<void *>(&_array_20);
_array_10.data[5] = 11;
_array_20.data[5] = 22;
std::cout << "using template\n";
print_element<10>(0, 5);
print_element<20>(1, 5);
std::cout << "\nwithout template\n";
print_element(0, 5);
print_element(1, 5);
std::cout << "\nusing data_view\n";
print_element(my_data_view(_array_10), 5);
print_element(my_data_view(_array_20), 5);
}
You could create a dynamic view class that don't allocate:
struct my_data_view
{
int array_length;
std::span<int> something;
std::span<int> data;
template<int length>
my_data_view(my_data<length> const& data) :
array_length{length}, something{data.something}, data{data.data}
{}
};
Spans simply are a pointer and a size. If you don't have access to std::span (which is from C++20) you can simply replace those member with int* and use array_length for the size.
This my_data_view type is used like that:
void
print_element(my_data_view view, int element)
{
int length = view.array_length;
int data_to_print = view.data[element];
std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
}
This is the code that will work both with std::span and simple int*.
My module tries to do things along the lines of the following program: sub-functions try to modify a structure's elements and give it back to the function to whom the structure is passed by reference.
#include <iostream>
#include <vector>
using namespace std;
struct a
{
int val1;
vector<int> vec1;
};
struct a* foo();
void anotherfunc(struct a &input);
int main()
{
struct a *foo_out;
foo_out = foo();
cout<< "Foo out int val: "<< foo_out->val1<<"\n";
cout<< "Foo out vector size: "<< foo_out->vec1.size()<< "\n";
cout<< "Foo out vector value1: "<< foo_out->vec1.at(0)<< "\n";
cout<< "Foo out vector value2: "<< foo_out->vec1.at(1)<< "\n";
return 0;
}
struct a *foo()
{
struct a input;
input.val1=729;
anotherfunc(input);
return &input;
}
void anotherfunc(struct a &input)
{
input.vec1.push_back(100);
input.vec1.push_back(1000);
input.vec1.push_back(1024);
input.vec1.push_back(3452);
cout<< "Anotherfunc():input vector value1: "<< input.vec1.at(0)<< "\n";
cout<< "Anotherfunc():input vector value2: "<< input.vec1.at(1)<< "\n";
cout<< "Anotherfunc():input int val: "<< input.val1<< "\n";
}
I am expecting the main function to contain the modified integer value in structure (729), and also the vector values (100,10000,1024 and 3452). On the contrary, main has none of these values, and on g++, the program shows a strange behaviour: main() shows that there are 4 elements in the vector inside structure, but when trying to print the values, segfaults.
After some more thought, I assume my question is : "Are structure members of structure passed by reference, passed ONLY by value ?" Should I not expect that vector to have the values set by functions to whom the entire structure is passed by reference? Kindly help.
Vijay
struct a *foo()
{
struct a input;
input.val1=729;
anotherfunc(input);
return &input;
}
You are returning pointer on the local object (it will be destroyed on exit from function), so, there is dangling pointer here and your program has undefined behaviour.
As ForeEveR says, the pointer you are returning is pointing to memory which is no longer guaranteed to contain a valid object. If you want this behavior, allocate input on the heap as follows:
a * foo ()
{
a * input = new input;
input->val1 = 729;
anotherfunc (*input);
return input;
}
Now it is the responsibility of whoever calls foo to free this memory, for example
{
a * foo_out = foo();
// do stuff with foo_out
delete foo_out; foo_out = 0;
}
At some point you will realize that keeping track of who allocated which objects is tedious, when this happens you should look up "smart pointers".
First of all, there is nothing terribly magical about "structures" in C++ — you should treat them like any other type. In particular, you don't need to write the keyword struct everywhere.
So here's your code in more idiomatic C++ (also re-ordered to avoid those wasteful pre-declarations):
#include <iostream>
#include <vector>
using namespace std;
struct a
{
int val1;
vector<int> vec1;
};
void bar(a& input)
{
input.vec1.push_back(100);
input.vec1.push_back(1000);
input.vec1.push_back(1024);
input.vec1.push_back(3452);
cout << "bar():input vector value1: " << input.vec1.at(0) << "\n";
cout << "bar():input vector value2: " << input.vec1.at(1) << "\n";
cout << "bar():input int val: " << input.val1 << "\n";
}
a* foo()
{
a input;
input.val1=729;
bar(input);
return &input;
}
int main()
{
a* foo_out = foo();
cout << "Foo out int val: " << foo_out->val1 << "\n";
cout << "Foo out vector size: " << foo_out->vec1.size() << "\n";
cout << "Foo out vector value1: " << foo_out->vec1.at(0) << "\n";
cout << "Foo out vector value2: " << foo_out->vec1.at(1) << "\n";
}
Now, as others have pointed out, foo() is broken in that it returns a pointer to a local object.
Why all the pointer trickery? If you're worried about copying that vector, then you can dynamically-allocate the a object and use a shared pointer implementation to manage that memory for you:
void bar(shared_ptr<a> input)
{
input->vec1.push_back(100);
input->vec1.push_back(1000);
input->vec1.push_back(1024);
input->vec1.push_back(3452);
cout << "bar():input vector value1: " << input->vec1.at(0) << "\n";
cout << "bar():input vector value2: " << input->vec1.at(1) << "\n";
cout << "bar():input int val: " << input->val1 << "\n";
}
shared_ptr<a> foo()
{
shared_ptr<a> input(new a);
input->val1 = 729;
bar(input);
return input;
}
Otherwise, just pass it around by value.
The following code prints '2' four times. Why does it never print '1'? Can someone explain me exactly what is happening here?
#include <iostream>
int main () {
union IntegersUnion {
int a;
int b;
};
IntegersUnion q;
q.a = 1;
q.b = 2;
std::cout << "(*(&q.a)) = " << (*(&q.a)) << std::endl;
std::cout << "(*(&q.b)) = " << (*(&q.b)) << std::endl;
std::cout << "(*(&(q.a))) = " << (*(&(q.a))) << std::endl;
std::cout << "(*(&(q.b))) = " << (*(&(q.b))) << std::endl;
return 0;
}
A union shares the memory between its members. By doing:
q.a = 1;
q.b = 2;
the second assignment overwrites the a.
union uses the same memory for all of its members.
So, when you assign q.b = 2;, q.a will be 2, too.
Every item in the union refers to the same location.
The most common use of union is something like this:
struct {
int dataTypeID;
union {
char char_here;
int number_here;
}
} incoming_data;
In this example, incoming_data is data imported from a file, where dataTypeID tells you what kind of data it is. (There are many file formats which optimize space in this fashion.)
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;
}