I have this implementation:
//header file:
InfoTables* localInforTable;
typedef txdr_int32 InfoTable;
typedef struct
{
int sendID;
InfoTable *data;
} InfoTables;
// in cpp file
void Retrieval::InfoTableCallBack(int sendID,
InfoTables& infoTables)
{
localInforTable = new InfoTables();
localInforTable.sendId=sendID;
localInforTable->data = infoTables.data;
printf("Data %d, %d\n", localInforTable.sendId, localInforTable->data[0]); // correct data
}
void Retrieval::CheckInfoData()
{
printf("Data %d, %d\n", localInforTable.sendId, localInforTable->data[0]); // sendID is OK but data9[0] is just printing the address
}
I want to copy inforTables in the method InforTableCallBack to a local variable that I can use for other methods. However the data is clean up in CheckInfoData()?
There are various errors with the code. First, data does not point to any allocated memory. Second, memcpy will simply not work for a user defined types that are not trivially copyable. You could use MyData's assignment operator instead:
void myMethod1(Mydata &otherdata)
{
*data = otherdata;
}
Adding to juanchopanza's answer:
assuming that the code has a typo (and if it really is memcpy())
memcpy(&data, &otherdata, sizeof(otherdata)); will simply not work correctly because data is a pointer already. and '&' on a pointer is address of the pointer = simply wrong usage of memcpy
Related
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});
}
}
I have been given this definitions, the function should return what is in info->phrase. However info->phrase can contain a string in which case I can only make it return the first char on info->phrase. Is there a way to make a string compatible with the char type? I am new to c++.
struct rep_info {
int num;
char *phrase;
};
I´ve tried few thing but get type errors, this was my latest attempt
char *phrase_info(rep_info info) {
char text[std::strlen(info->phrase) + 1];
text = info->phrase;
return text;
}
Since you said you have been given these definitions, let's fix the problem with the current setup first. Looking at your function, you are trying to copy into this local array (incorrectly I might add), and return this local variable. There are a number of things wrong with this, including the syntax and the fact that the local variable is destroyed when the function exits.
If you just need to get the value of the phrase member variable, the simplest solution would be to just access the member variable directly and return it:
char *phrase_info(rep_info info) {
return info.phrase; //since info is not a pointer, use the '.' accessor
}
If you mean to pass a pointer to the function, you would re-write it like this:
char *phrase_info(rep_info *info) {
return info->phrase;
}
But it seems like you feel the need to copy the contents of info->phrase into a new memory space? If so, then you would do something like this where you first allocate new memory and return this buffer:
char *phrase_info(rep_info *info) {
char *buf = new char[std::strlen(info->phrase) + 1];
std::strcpy(buf,info->phrase); //copies info->phrase into buf
return buf;
}
You would then need to use delete on the returned memory value to clean up the memory allocated by new, otherwise you will have a memory leak.
Overall, all the above solution would potentially solve the problem given some parameters you haven't made clear. To round this out, this should be written more like:
class rep_info {
private:
int num;
std::string phrase;
public:
rep_info(int n, std::string p) : num(n), phrase(p) {}
std::string get_phrase() { return phrase; }
// other functions
};
//later in the code
rep_info info(...);
info.get_phrase();
Ideally, you would wrap these member variables into their own object with corresponding member functions that can get and set these values. Moreover, for handling strings in C++, std::string is the preferred option for storing, copying, modifying, etc. strings over the older char * C-style string.
I having difficulty saving a pointer argument that my mock receives.
#define SIZE_OF_DATA
typedef struct {
uint32_t someValue1;
uint16_t someValue2;
// other values here
} LargeStruct;
class SomeClass {
public:
// assume sendData is a generic function where data is actually pointer to a LargeStruct
void sendData(const uint8_t* data, const uint16_t size);
}
class MockClass : public SomeClass {
public:
MOCK_METHOD2(sendData, void(const uint8_t*, const uint16_t));
};
I want to save the first argument to sendData (the pointer) and look at the data it points to (it points to a large struct, so I don't want to copy by value):
TEST(SomeFixture, sendData_checkSentDataIsValid) {
MockClass mock;
const uint8_t *pData;
EXPECT_CALL(mock, sendData(_, SIZE_OF_DATA)).WillOnce(SaveArg<0>(&pData));
// do something here that calls sendData()
// hopefully data should point to the same data that was passed in to the method
LargeStruct *ls = (LargeStruct *)pData;
// now verify that the data is ok...
// some expectations here
EXPECT_EQ(SOMEVALUEIWANT, ls->someValue1);
}
However, the data pointed to by pData is wrong - I think I appear to be saving the pointer value into the struct, rather than saving the pointer.
I think the problem lies in the variable I pass to SaveArg, but I can't seem to get it in a version that compiles and gives me the correct answer. Any pointers please?
I just ran into the same situation, and in my case, I had to make sure that the pointer passed into the equivalent of your sendData() function was not pointing to an automatic variable on the stack. Otherwise, by the time you access the pointer, the contents will have changed. I found that less than helpful, so I decided to define a customized alternative to SaveArg like this:
ACTION_TEMPLATE(SaveSomeValue1,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_1_VALUE_PARAMS(pointer))
{
const void * data = ::std::tr1::get<k>(args);
const LargeStruct* ls = (const LargeStruct *)data;
*pointer = ls->someValue1;
}
You can then use it like this:
uint32_t someValue1;
EXPECT_CALL(mock, sendData(_, SIZE_OF_DATA))
.WillOnce(SaveSomeValue1<0>(&someValue1));
//...
EXPECT_EQ(SOMEVALUEIWANT, someValue1);
You can create one void pointer as a buffer and save argument inside that buffer. After that you should cast the buffer to your large structure.
TEST(SomeFixture, sendData_checkSentDataIsValid) {
MockClass mock;
LargeStruct *ls;
void *buffer;
EXPECT_CALL(mock, sendData(_, SIZE_OF_DATA))
.WillOnce(SaveArg<0>(&buffer));
// do something here that calls sendData()
ls = static_cast<LargeStruct *>(buffer);
EXPECT_EQ(SOMEVALUEIWANT, ls->someValue1);
}
I have the following structure, class and function snippet:
structure:
struct myData
{
short index;
char name[32];
}
class:
class myFoo
{
...
public:
short count;
myData** data;
...
}
function:
int Do_Bar(myFoo vFoo)
{
...
myData* data = *vFoo.data;
for (short i=0; i<vFoo.count; ++i)
{
Printf("%3d %s", data.index, data.name);
}
...
}
function call:
...
myFoo foo;
SomeAPI_GetCompleteObjectList(&foo);
Do_Bar(foo);
...
But my code crashes with these code. But if I removed the parameter and create a myFoo class in Do_Bar() function instead, the code works fine:
int Do_Bar(myFoo vFoo)
{
myFoo foo;
SomeAPI_GetCompleteObjectList(&foo);
...
myData* data = *vFoo.data;
for (short i=0; i<vFoo.count; ++i)
{
Printf("%3d %s", data.index, data.name);
}
...
}
Why is it? And how to resolve this?
EDIT1:
I forgot to mention that the initializations of foo is done before the function call. This was initialized using an API.
I modified the code for this.
You have not given memory to pointer data in line myData* data and trying to assign something to it.Alternative method are either
define myData data then use &data as pointer
or allocate memory using dynamic memory allocation.
You have a couple of undefined behaviors in that little piece of code...
You have a double-pointer, but never "point" either of them to anything. This mean they will point to random memory locations.
You print an uninitialized character array, which means it contains random data.
And since you don't do any initialization at all, foo.count will also contain a random value, which may be negative or very large.
And last bot not least, like I said in my comment, that code should not even compile as you use the wrong syntax for the access of the members in the structure.
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 & 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 & 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!