duplicate typedef struct through pointer - c++

I have following typedef defined and *ButtonSettingPtr as a pointer:
typedef struct
{
void *next;
char** buttonsetting;
char* currentsetting;
uint16_t presetid;
uint16_t currentcounter;
uint16_t maxsize;
uint16_t buttonid;
} ButtonSetting;
typedef ButtonSetting *ButtonSettingPtr;
class Options {
private:
ButtonSettingPtr settings;
ButtonSettingPtr preset1;
public:
Options();
void newSetting(char** _setting, uint16_t _maxsize, uint16_t _buttonid);
// some other stuff defined here
}
With the newSetting() function I am adding several new entries to my
typedef instance! Now, I would like to save all these settings
(this->settings) into another pointer (this->preset1) via memcpy to
later call them up again via another function, since I am using
this->settings in a couple of other functions (getCurrentSetting) which
are working quite well etc.
char *Options::getCurrentSetting(uint16_t _buttonid) {
ButtonSettingPtr setting = (ButtonSettingPtr)this->settings;
while (setting != NULL)
{
if (setting->buttonid == _buttonid) {
char * tmpsetting =
setting->buttonsetting[setting->currentcounter];
return tmpsetting;
}
setting = (ButtonSettingPtr)setting->next;
}
return NULL;
}
Here's the problem:
void Options::savePreset() {
memcpy(&this->preset1,&this->settings,sizeof(&this->settings));
}
void Options::loadPreset() {
memcpy(&this->settings,&this->preset1,sizeof(&this->preset1));
}
It seems that my preset1 pointer is always exactly the same as
this->settings even though i am changing settings inbetween. I
understand that with the &amp sign it literally copies the address of
that pointer, so to no surprise they will both always be exactly the
same. But what I would like to copy is rather all bytes and point them
to preset1, so I can recall all the settings later again.
So, without the &amp sign my code just hangs:
void Options::savePreset() {
memcpy(this->preset1,this->settings,sizeof(this->settings));
}
void Options::loadPreset() {
memcpy(this->settings,this->preset1,sizeof(this->preset1));
}
Do I have to malloc the this->preset1 pointer before I memcpy everything
to it? The whole code is compiled using avr-libc for an atmega chip.
Thanks in advance for any useful hint!
ps: My understanding of C++ has been surely better when I was younger!

It looks like you're doing a home-grown singly linked list. If you replace that with std::vector you'll find that copying one to the other is as easy as preset1 = settings; (you don't need to put this-> in front of everything unless you just prefer that style).
You might also want to replace the char** inside the class with std::vector<string> as well, then the actual strings will be copied.

Yes, you do need to malloc preset1 (no need to dereference it with this-> inside a member function. If you want to make it clear that it's a class data member, name it m_preset1 or mPreset1 as you like).
So, in your constructor set preset1 to NULL. Then in your member function you can:
void Options::savePreset() {
if (preset1 == NULL) {
preset1 = (ButtonSettingPtr)malloc(sizeof (ButtonSetting));
}
memcpy(preset1, settings, sizeof(ButtonSetting));
}
Don't forget to add error checking. But really, I don't see any reason not to statically allocate space instead and avoid memory allocation issues:
class Options {
private:
ButtonSetting settings;
ButtonSetting preset1;
public:
Options();
void newSetting(char** _setting, uint16_t _maxsize, uint16_t _buttonid);
// some other stuff defined here
}
void Options::savePreset() {
memcpy(&preset1, &settings, sizeof(ButtonSetting));
}
Note that sizeof(this->settings) will always be 4 or 8 (depending on 32 or 64 bit CPU) because you're asking for the size of a pointer, not the size of the structure.

sizeof(&this->settings)
will return the size of a pointer because it is effectively a pointer.
sizeof(this->settings)
will return the size of a pointer because it is a pointer.
sizeof(*this->settings)
will return the size of the anonymous struct that settings points too.
And as for the question of needing to malloc space for
this->preset1
depends on you code. But it for sure needs to point to valid memory!

Related

Using 'memcpy()' inside a class with a union

I have a class foo that manages data using small buffer optimization (SBO).
When size < 16, the data is held locally (in buffer), otherwise it is stored on the heap, with reserved holding the allocated space.
class foo {
static const int sbo_size = 16;
long size = 0;
char *ptr;
union {
char buffer[sbo_size];
long reserved;
};
public:
foo()
{
for (int i = 0; i < sbo_size; ++i)
buffer[i] = 0;
}
void clone(const foo &f)
{
// release 'ptr' if necessary
if (f.size < sbo_size)
{
memcpy(this, &f, sizeof(foo));
ptr = buffer;
} else
{
// handle non-sbo case
}
}
};
Question about clone():
With the SBO case, it may not be clear for the compiler that union::buffer will be used.
is it correct to use memcpy and set ptr accordingly?
If you can use C++17, I would side-step any potential type-punning problems by using std::variant in place of a union.
Although this uses a small amount of storage internally to keep track of the current type it contains, it's probably a win overall as your ptr variable can disappear (although that should be inside your union anyway).
It's also typesafe, which a union is not (because std::get will throw if the variant doesn't contain the desired type) and will keep track of the type of data it contains simply by assigning to it.
The resulting class fragment might look something like this (no doubt this code can be improved):
class foo
{
private:
static const size_t sbo_size = 16;
using small_buf = std::array <char, sbo_size>;
size_t size = 0;
std::variant <small_buf, char *> buf = { };
public:
void clone (const foo &f)
{
char **bufptr = std::get_if <char *> (&buf);
if (bufptr)
delete [] *bufptr;
size = f.size;
if (size < sbo_size)
buf = std::get <small_buf> (f.buf);
else
{
buf = new char [size];
std::memcpy (std::get <char *> (buf), std::get <char *> (f.buf), size);
}
}
};
Notes:
You will see that I've used std::array instead of a C-style array because std:array has lots of nice features that C-style arrays do not
Why clone and not a copy constructor?
if you want foo to have an empty state (after being default constructed, say), then you can look into the strangely named std::monostate.
For raw storage, std::byte is probably to be preferred over char.
Fully worked example here.
Edit: To answer the question as posed, I am no language lawyer but it seems to me that, inside clone, the compiler has no clue what the active member of f might be as it has, in effect, been parachuted in from outer space.
In such circumstances, I would expect compiler writers to play it safe and set the active member of the union to "don't know" until some concrete information comes along. But (and it's a big but), I wouldn't like to bet my shirt on that. It's a complex job and compiler writers do make mistakes.
So, in a spirit of sharing, here's a slightly modified version of your original code which fixes that. I've also moved ptr inside your union since it clearly belongs there:
class foo {
static const int sbo_size = 16;
long size = 0;
union {
std::array <char, sbo_size> buffer; // changing this
char *ptr;
long reserved;
};
public:
foo()
{
for (int i = 0; i < sbo_size; ++i)
buffer[i] = 0;
}
void clone(const foo &f)
{
// release 'ptr' if necessary
if (f.size < sbo_size)
{
buffer = f.buffer; // lets me do this
ptr = buffer.data ();
} else
{
// handle non-sbo case
}
}
};
So you can see, by using std::array for buffer (rather than one of those hacky C-style arrays), you can directly assign to it (rather than having to resort to memcpy) and the compiler will then make that the active member of your union and you should be safe.
In conclusion, the question is actually rather meaningless since one shouldn't (ever) need to write code like that. But no doubt someone will immediately come up with something that proves me wrong.

C++ Constant anonymous instance with aggregate initialization

Basically Im wanting to fetch a pointer of a constant and anonymous object, such as an instance of a class, array or struct that is inialised with T {x, y, z...}. Sorry for my poor skills in wording.
The basic code that Im trying to write is as follows:
//Clunky, Im sure there is an inbuilt class that can replace this, any information would be a nice addition
template<class T> class TerminatedArray {
public:
T* children;
int length;
TerminatedArray(const T* children) {
this->children = children;
length = 0;
while ((unsigned long)&children[length] != 0)
length++;
}
TerminatedArray() {
length = 0;
while ((unsigned long)&children[length] != 0)
length++;
}
const T get(int i) {
if (i < 0 || i >= length)
return 0;
return children[i];
}
};
const TerminatedArray<const int> i = (const TerminatedArray<const int>){(const int[]){1,2,3,4,5,6,0}};
class Settings {
public:
struct Option {
const char* name;
};
struct Directory {
const char* name;
TerminatedArray<const int> const children;
};
const Directory* baseDir;
const TerminatedArray<const Option>* options;
Settings(const Directory* _baseDir, const TerminatedArray<const Option> *_options);
};
//in some init method's:
Settings s = Settings(
&(const Settings::Directory){
"Clock",
(const TerminatedArray<const int>){(const int[]){1,2,0}}
},
&(const TerminatedArray<const Settings::Option>){(const Settings::Option[]){
{"testFoo"},
{"foofoo"},
0
}}
);
The code that I refer to is at the very bottom, the definition of s. I seem to be able to initialize a constant array of integers, but when applying the same technique to classes, it fails with:
error: taking address of temporary [-fpermissive]
I don't even know if C++ supports such things, I want to avoid having to have separate const definitions dirtying and splitting up the code, and instead have them clean and anonymous.
The reason for wanting all these definitions as constants is that Im working on an Arduino project that requires efficient balancing of SRAM to Flash. And I have a lot of Flash to my disposal.
My question is this. How can I declare a constant anonymous class/struct using aggregate initialization?
The direct (and better) equivalent to TerminatedArray is std::initializer_list:
class Settings {
public:
struct Option {
const char* name;
};
struct Directory {
const char* name;
std::initializer_list<const int> const children;
};
const Directory* baseDir;
const std::initializer_list<const Option>* options;
Settings(const Directory& _baseDir, const std::initializer_list<const Option>& _options);
};
//in some init method's:
Settings s = Settings(
{
"Clock",
{1,2,0}
},
{
{"testFoo"},
{"foofoo"}
}
);
https://godbolt.org/z/8t7j0f
However, this will almost certainly have lifetime issues (which the compiler tried to warn you about with "taking address of temporary"). If you want to store a (non-owning) pointer (or reference) then somebody else should have ownership of the object. But when initializing with temporary objects like this, nobody else does. The temporaries die at the end of the full expression, so your stored pointers now point to dead objects. Fixing this is a different matter (possibly making your requirements conflicting).
Somewhat relatedly, I'm not sure whether storing a std::initializer_list as class member is a good idea might. But it's certainly the thing you can use as function parameter to make aggregate initialization nicer.
&children[length] != 0 is still true or UB.
If you don't want to allocate memory, you might take reference to existing array:
class Settings {
public:
struct Option {
const char* name;
};
struct Directory {
const char* name;
std::span<const int> const children;
};
const Directory baseDir;
const std::span<const Option> options;
Settings(Directory baseDir, span<const Option> options);
};
//in some method:
const std::array<int, 3> ints{{1,2,0}};
const std::array<Settings::Option> options{{"testFoo"}, {"foofoo"}};
Settings s{"Clock", {ints}}, options};
First, you're not aggregate-initializing anything. This is uniform initialization and you're calling constructors instead of directly initializing members. This is because your classes have user-defined constructors, and classes with constructors can't be aggregate-initialized.
Second, you're not really able to "initialize a constant array of integers". It merely compiles. Trying to run it gives undefined behavior - in my case, trying to construct i goes into an infinite search for element value 0.
In C++, there's values on the stack, there's values on the heap and there's temporary values (I genuinely apologize to anyone who knows C++ for this statement).
Values on the heap have permanent addresses which you can pass around freely.
Values on the stack have temporary addresses which are valid until
the end of the block.
Temporary values either don't have addresses
(as your compiler warns you) or have a valid address for the duration
of the expression they're used for.
You're using such a temporary to initialize i, and trying to store and use the address of a temporary. This is an error and to fix it you can create your "temporary" array on the stack if you don't plan to use i outside of the block where your array will be.
Or you can create your array on the heap, use its address to initialize i, and remember to explicitly delete your array when you're done with it.
I recommend reading https://isocpp.org/faq and getting familiar with lifetime of variables and memory management before attempting to fix this code. It should give you a much better idea of what you need to do to make your code do what you want it to do.
Best of luck.

Save reference to void pointer in a vector during loop iteration

Guys I have a function like this (this is given and should not be modified).
void readData(int &ID, void*&data, bool &mybool) {
if(mybool)
{
std::string a = "bla";
std::string* ptrToString = &a;
data = ptrToString;
}
else
{
int b = 9;
int* ptrToint = &b;
data = ptrToint;
}
}
So I want to use this function in a loop and save the returned function parameters in a vector (for each iteration).
To do so, I wrote the following struct:
template<typename T>
struct dataStruct {
int id;
T** data; //I first has void** data, but would not be better to
// have the type? instead of converting myData back
// to void* ?
bool mybool;
};
my main.cpp then look like this:
int main()
{
void* myData = nullptr;
std::vector<dataStruct> vec; // this line also doesn't compile. it need the typename
bool bb = false;
for(int id = 1 ; id < 5; id++) {
if (id%2) { bb = true; }
readData(id, myData, bb); //after this line myData point to a string
vec.push_back(id, &myData<?>); //how can I set the template param to be the type myData point to?
}
}
Or is there a better way to do that without template? I used c++11 (I can't use c++14)
The function that you say cannot be modified, i.e. readData() is the one that should alert you!
It causes Undefined Behavior, since the pointers are set to local variables, which means that when the function terminates, then these pointers will be dangling pointers.
Let us leave aside the shenanigans of the readData function for now under the assumption that it was just for the sake of the example (and does not produce UB in your real use case).
You cannot directly store values with different (static) types in a std::vector. Notably, dataStruct<int> and dataStruct<std::string> are completely unrelated types, you cannot store them in the same vector as-is.
Your problem boils down to "I have data that is given to me in a type-unsafe manner and want to eventually get type-safe access to it". The solution to this is to create a data structure that your type-unsafe data is parsed into. For example, it seems that you inteded for your example data to have structure in the sense that there are pairs of int and std::string (note that your id%2 is not doing that because the else is missing and the bool is never set to false again, but I guess you wanted it to alternate).
So let's turn that bunch of void* into structured data:
std::pair<int, std::string> readPair(int pairIndex)
{
void* ptr;
std::pair<int, std::string> ret;
// Copying data here.
readData(2 * pairIndex + 1, ptr, false);
ret.first = *reinterpret_cast<int*>(ptr);
readData(2 * pairIndex + 2, ptr, true);
ret.second = *reinterpret_cast<std::string*>(ptr);
}
void main()
{
std::vector<std::pair<int, std::string>> parsedData;
parsedData.push_back(readPair(0));
parsedData.push_back(readPair(1));
}
Demo
(I removed the references from the readData() signature for brevity - you get the same effect by storing the temporary expressions in variables.)
Generally speaking: Whatever relation between id and the expected data type is should just be turned into the data structure - otherwise you can only reason about the type of your data entries when you know both the current ID and this relation, which is exactly something you should encapsulate in a data structure.
Your readData isn't a useful function. Any attempt at using what it produces gives undefined behavior.
Yes, it's possible to do roughly what you're asking for without a template. To do it meaningfully, you have a couple of choices. The "old school" way would be to store the data in a tagged union:
struct tagged_data {
enum { T_INT, T_STR } tag;
union {
int x;
char *y;
} data;
};
This lets you store either a string or an int, and you set the tag to tell you which one a particular tagged_data item contains. Then (crucially) when you store a string into it, you dynamically allocate the data it points at, so it will remain valid until you explicitly free the data.
Unfortunately, (at least if memory serves) C++11 doesn't support storing non-POD types in a union, so if you went this route, you'd have to use a char * as above, not an actual std::string.
One way to remove (most of) those limitations is to use an inheritance-based model:
class Data {
public:
virtual ~Data() { }
};
class StringData : public Data {
std::string content;
public:
StringData(std::string const &init) : content(init) {}
};
class IntData : public Data {
int content;
public:
IntData(std::string const &init) : content(init) {}
};
This is somewhat incomplete, but I think probably enough to give the general idea--you'd have an array (or vector) of pointers to the base class. To insert data, you'd create a StringData or IntData object (allocating it dynamically) and then store its address into the collection of Data *. When you need to get one back, you use dynamic_cast (among other things) to figure out which one it started as, and get back to that type safely. All somewhat ugly, but it does work.
Even with C++11, you can use a template-based solution. For example, Boost::variant, can do this job quite nicely. This will provide an overloaded constructor and value semantics, so you could do something like:
boost::variant<int, std::string> some_object("input string");
In other words, it's pretty what you'd get if you spent the time and effort necessary to finish the inheritance-based code outlined above--except that it's dramatically cleaner, since it gets rid of the requirement to store a pointer to the base class, use dynamic_cast to retrieve an object of the correct type, and so on. In short, it's the right solution to the problem (until/unless you can upgrade to a newer compiler, and use std::variant instead).
Apart from the problem in given code described in comments/replies.
I am trying to answer your question
vec.push_back(id, &myData<?>); //how can I set the template param to be the type myData point to?
Before that you need to modify vec definition as following
vector<dataStruct<void>> vec;
Now you can simple push element in vector
vec.push_back({id, &mydata, bb});
i have tried to modify your code so that it can work
#include<iostream>
#include<vector>
using namespace std;
template<typename T>
struct dataStruct
{
int id;
T** data;
bool mybool;
};
void readData(int &ID, void*& data, bool& mybool)
{
if (mybool)
{
data = new string("bla");
}
else
{
int b = 0;
data = &b;
}
}
int main ()
{
void* mydata = nullptr;
vector<dataStruct<void>> vec;
bool bb = false;
for (int id = 0; id < 5; id++)
{
if (id%2) bb = true;
readData(id, mydata, bb);
vec.push_back({id, &mydata, bb});
}
}

Accessing variable outside scope of a callback c++

I have been beating my head around this issue of static versus non-static, callback functions, function pointers, etc... My goal is to access data of a struct outside the scope of my callback interface. I am trying to do this within my class called TextDetect. I thought I was on track when I asked this question: Avoiding a static member function in c++ when using a callback interface from C
However, I still can't access the data without losing scope over the data that I am most interested. At runtime, I get "Access violation reading location ..." I'll point it out below where it fails.
I implemented the answer to my previous question as the following class, shown entirely (Note: vtrInitialize is part of a 3rd party api code int vtrInitialize(const char *inifile, vtrCallback cb, void *calldata);):
class TextDetect {
const char * inifile;
vtrImage *vtrimage;
int framecount;
public:
TextDetect();
~TextDetect();
void vtrCB(vtrTextTrack *track);
static void vtrCB_thunk(vtrTextTrack *track, void *calldata);
int vtrTest(cv::Mat);
bool DrawBox(cv::Mat&);
vtrTextTrack *texttrack;
};
TextDetect::TextDetect() : inifile("vtr.ini")
{
if (vtrInitialize(inifile, vtrCB_thunk, static_cast<void *>(this) ) == -1)
std::cout << "Error: Failure to initialize" << std::endl;
vtrimage = new vtrImage;
}
int TextDetect::vtrTest(cv::Mat imagetest)
{
/*store image data in an image structure*/
}
void TextDetect::vtrCB(vtrTextTrack *track)
{
/*send data to command line from callback */
I've tried copying the data I need a variety of ways and nothing works (this code is a continuation from above):
//texttrack = track;
//texttrack = new vtrTextTrack (*track);
memcpy(texttrack,track,sizeof(*track));
//vtrTextTrackFree(track);
}
void TextDetect::vtrCB_thunk(vtrTextTrack *track, void *calldata)
{
static_cast<TextDetect *>(calldata)->vtrCB(track);
}
This is the member function were I want the data to be used. Texttrack is public member so I might need it outside my class as well (this code is a continuation from above):
bool TextDetect::DrawBox(cv::Mat& tobeboxed)
{
And I get the access violation error at runtime here at this line of code (this code is a continuation from above):
if (texttrack->best->ocrconf > 90)
{
/*do some more stuff*/
}
}
Hopefully I'm understanding this correctly.
It seems to me that the problem is trying to copy those vtrTextTrack structs improperly.
This:
//texttrack = track;
just copies the pointer. If the owner of the struct (probably the caller of the callback function) destroys/deletes the vtrTextTrack, then you're holding on to an invalid pointer.
This one:
memcpy(texttrack,track,sizeof(*track));
will copy all the members of the vtrTextTrack, but will not copy what's being pointed to by it's member pointers (e.g. texttrack->best). Again, if the owner destroys/deletes the track, then you're holding on to invalid pointers.
And since
//texttrack = new vtrTextTrack (*track);
didn't work, I'm guessing that vtrTextTrack doesn't provide a copy constructor.
As for a workaround, first check if your third party library provides a function to copy these structs. If that's not the case (could this be by design?), then you may have to implement one yourself. This might be hard because there might be all kinds of internals that you don't know about. If you don't need the whole vtrTextTrack, I'd say define another struct and store only the information you need. Something along the lines of
SomeType* bestCopier(SomeType* src)
{
SomeType* temp;
/* copy over struct */
return temp;
}
Foo* fooCopier(Foo* src)
{
/*...*/
}
struct myTextTrack
{
public:
myTextTrack(vtrTextTrack* src)
{
//copy over stuff
m_best = bestCopier(src->best);
m_foo = fooCopier(src->foo);
}
private:
/* the members you care about*/
SomeType* m_best;
Foo * m_foo;
}

How to modify a C++ structure with int *

I have the following structure:
struct CountCarrier
{
int *CurrCount;
};
And this is what I want to do:
int main()
{
CountCarrier carrier = CountCarrier();
*(carrier.CurrCount) = 2; // initialize the *(carrier.CurrCount) to 2
IncreaseCount(&carrier); // should increase the *(carrier.CurrCount) to 3
}
void IncreaseCount(CountCarrier *countCarrier)
{
int *currCounts = countCarrier->CurrCount;
(*currCounts)++;
}
So, my intention is specified in the comments.
However, I couldn't get this to work. For starters, the program throws an exception at this line:
*(carrier.CurrCount) = 2;
And I suspect the following line won't work as well. Anything I did wrong?
struct CountCarrier
{
int *CurrCount; //No memory assigned
};
You need to allocate some valid memory to the pointer inside the structure to be able to put data in this.
Unless you do so, What you ar trying to do is attempting to write at some invalid address, which results in an Undefined Behavior, which luckiy in this case shows up as an exception.
Resolution:
struct CountCarrier
{
int *CurrCount; //No memory assigned
CountCarrier():CurrCount(new(int))
{
}
};
Suggestion:
Stay away from dynamic allocations as long as you can.
When you think of using pointers always think whether you really need one. In this case it doesn't really seem that you need one, A simple int member would be just fine.
You need to create the pointer. ie. carrier->CurrCount = new int;
*(carrier.CurrCount)
This is dereferencing the pointer carrier.CurrCount, but you never initialized it. I suspect this is what you want:
carrier.CurrCount = new int(2);
I seriously doubt that your program throws an exception at the line:
*(carrier.CurrCount) = 2;
While throwing an exception is certainly allowed behaviour, it seems much more likely that you encountered an access violation that caused the process to be killed by the operating system.
The problem is that you are using a pointer, but your pointer is not initialised to point at anything. This means that the result of the pointer dereference is undefined.
In this situation there does not seem to be any advantage to using a pointer at all. Your CurrCount member would work just as well if it was just a plain int.
If you are using C++, then you should encash its facilities. Instead of correcting your code, I am showing here that how the code should look like:
struct CountCarrier
{
int CurrCount; // simple data member
CountCarrier(int count) : CurrCount(count) {} // constructor
CountCarrier& operator ++ () // overloaded operator
{
++ CurrCount;
return *this;
}
};
We are overloading operator ++, because you have only one data member. You can replace with some named method also, like void IncrementCount().
CountCarrier carrier(2);
++ carrier;
As Als said, you need to provide some memory for the code to work.
But why make it so complicated? You don't need any pointers for the code you have to work. The "modern C++" way looks more like this:
struct CountCarrier
{
public:
CountCarrier(int currCount) : currCount(currCount) {}
void IncreaseCount() { ++currCount; }
int GetCount() const { return currCount; }
private:
int currCount;
};
int main()
{
CountCarrier carrier(2); // Initialize carrier.currCount to 2
carrier.IncreaseCount(); // Increment carrier.currCount to 3
}
Note how much cleaner and less error prone that is. Like I said, pick up a good introductory C++ book and read through it.