Reputation: 65
So I have the following code, a simplified version of what I want to do. I have a class with a member variable that I want to set to potentially a variety of different data types, depending on the situation (i just made a random struct for this test). I keep getting seg faults on the memcpy function though, and I have no idea why.
#include <cstdlib>
#include <iostream>
#include <assert.h>
#include <string>
#include <string.h>
#include <stdio.h>
using namespace std;
struct product
{
int price;
string name;
};
class object
{
public:
void setData(void *ptr);
void* data;
};
void object::setData(void *ptr)
{
assert(ptr);
memcpy(data, ptr, sizeof(ptr));
}
int main()
{
product* bag;
product ba;
bag = &ba;
bag->price = 5;
bag->name = "bag";
object test;
test.setData(bag);
cout<<test.data->name<<endl;
return 0;
}
Upvotes: 1
Views: 2756
Reputation: 14
I know this is an old post, but I don't like any of the answers, so for future readers.
When you cast an object to a void*, you loss the type information associated with it. That is why you can't use sizeof with a void* ptr. (This is probably also why memcpy doesn't do it this way). I think what you need here is to write a Template class. Then the code will know the type and the code should work.
template<class T>
class object
{
public:
void setData(T *ptr);
T* data;
};
void object::setData(T *ptr)
{
assert(ptr);
memcpy(data, ptr, sizeof(ptr));
}
Upvotes: 0
Reputation: 35440
Others have mentioned that the memcpy
is not correct due to using sizeof(void*)
as the number of bytes to copy. But changing the sizeof
to an appropriate value will just have you hit the next stumbling block with using memcpy
. You would probably encounter it as soon as you execute this line:
cout<<test.data->name<<endl
The reason is that data->name
is more than likely corrupted, invalid, or if you did actually see a name printed, the string is in an unstable state.
Basically, using memcpy
to set a struct to a certain value isn't going to work if the struct is not a POD type.
Your product
class has a member that is a non-POD type, namely std::string
. You cannot simply overlay a std::string
object with bytes of data from another std::string
object (which is what that memcpy
will be doing).
The same thing can be said for functions such as memset
or any C
oriented function that sets the bytes of what is pointed to with values. They cannot be used on non-POD types.
Unlike POD types, just doing a copy of bytes like that will corrupt the destination object. If that object contained, say a v-table, then you really would be ripping the destination object to shreds.
For non-POD types, use the proper C++ techniques, which include using assignment (data = ptr
).
Upvotes: 2
Reputation: 630
Also I suppose it could be problem here
cout<<test.data->name<<endl;
case data is void pointer so you need cast here
cout<<static_cast<product *>(test.data)->name<<endl;
Upvotes: 0
Reputation: 62553
Your code has multiple issues, but a direct cause of SIGSEGV is following line:
memcpy(data, ptr, sizeof(ptr));
which tries to copy a number of bytes into unallocated pointer data
.
On a side note, it looks like you are trying to achieve polymorphism in C++ using completely inapproriate methods.
Upvotes: 5