Initialization of dynamically allocated structures using shared pointer - initialization

I dont understand why initialization of dynamically allocated structure needs to be done like this (using shared ptr)
Just to notify that I am using C++11
If we have struct like this
struct Meme {
std::string s;
Meme* p;
}
and later in code, I need to dynamically allocated memory for this structure using shared_ptr, but I need to do instant initialization of structure.
Why it is done like this?
std::shared_ptr<Meme> novi=std::make_shared<Meme>(Meme{imena.at(i),nullptr});
part that confuses me is this one :
std::make_shared<Meme>(Meme{imena.at(i),nullptr});
If we set that shared_ptr points to struct Meme, why we need to specify again that initialization list is for struct Meme, by saying
(Meme{imena.at(i),nullptr})
Why this would not work:
std::shared_ptr<Meme> novi=std::make_shared<Meme>({imena.at(i),nullptr});
Is this maybe that initialization list cannot deduct that it should like convert to struct Meme because there is no direct usage of struct Meme(even though make_shared points to struct Meme) ?

make_shared forwards arguments to constructor.
Make shared_ptr
Allocates and constructs an object of type T passing args to its constructor, and returns an object of type shared_ptr that owns and stores a pointer to it (with a use count of 1).
This calls the copy constructor of Meme from new instance you create with Meme{imena.at(i),nullptr}.
std::shared_ptr<Meme> novi=std::make_shared<Meme>(Meme{imena.at(i),nullptr});
The correct way to construct it with make_shared from forwarded arguments is to create constructor in struct:
struct Meme {
std::string s;
Meme* p;
Meme(const std::string& s, Meme* p) : s(s), p(p) {}
};
std::shared_ptr<Meme> novi = std::make_shared<Meme>(imena.at(i),nullptr);
Also you can create an instance with (default) empty constructor and then set its members:
struct Meme {
std::string s;
Meme* p = nullptr;
};
std::shared_ptr<Meme> novi = std::make_shared<Meme>;
novi->s = imena.at(i);

Related

shared_ptr not changing object (Visual studio 2012)

I have a really strange problem. I can't modify the object I am pointing to with a shared_ptr.
Example code:
#include<memory>
#include<iostream>
using namespace std;
class foo
{
public:
int asd;
foo(){}
~foo(){}
};
void d(shared_ptr<foo> c)
{
c->asd = 3;
}
void main()
{
foo a;
a.asd = 5;
d(make_shared<foo>(a));
cout<<a.asd; //asd is still 5
}
As far as I know you can access the object pointed to by the shared_ptr by using the "->" operator, so what am I doing wrong here? How can I change the asd variable inside the class via the shared pointer?
// create a temporary object by copying a
// the shared pointer you pass to d function actually points to this temporary object
d(make_shared<foo>(a));
// allocate and store foo object in shared_ptr instead
auto p_a(make_shared<foo>());
p_a->asd = 3;
d(p_a);
... so what am I doing wrong here?
From cppreference on std::make_shared [emphasis mine]:
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
Constructs an object of type T and wraps it in a std::shared_ptr
using args as the parameter list for the constructor of T.
In your case, you supply an instance of foo as argument to std::make_shared, which will be used when constructing a new object of type foo; i.e., making use of the default supplied copy CTOR of foo (foo(const foo&)). This new object will be a temporary and only live for the call to d(...).

How to create a generic function to take hashtable name and a struct as parameters in a kernel module?

I'm currently writing a kernel module which uses multiple hashtables to store different structures. How would I go about implementing a single generic function which would take the hashtable name, hash key and structure to be stored as parameters and do the corresponding store operation?
Here is my hashtable and structure definition.
static DEFINE_HASHTABLE(count, 7);
struct mystruct {
int data ;
struct hlist_node my_hash_list ;
};
Here is my store code ( I seem to be getting a null pointer error if I increment temp->data directly instead of doing it my roundabout add and del way :( )
struct mystruct *temp;
struct mystruct *first;
temp = kmalloc(sizeof(struct mystruct),GFP_KERNEL);
first = kmalloc(sizeof(struct mystruct),GFP_KERNEL);
hash = command;
hash_for_each_possible(count, temp, my_hash_list,hash){
first->data=temp->data+1;
printk("Count: %d\n",first->data);
hash_add(count, &(first->my_hash_list), hash);
hash_del(&(temp->my_hash_list));
return;
}
first->data=1;
hash_add(count, &(first->my_hash_list), hash);
This is for the count hashtable and mystruct structure. Is it possible to create a kernel module function to have a placeholder pointer to any structure and kmalloc memory to that struct? Also how to pass the hashtable name as a parameter?
You cannot create a function which accepts name of the hashtable: it is prohibited by C language. So, your function may only accept a pointer to the hashtable. But because it accepts a pointer, you may no longer use macros like hash_add, which requires name.
You have 2 possibilites:
Creating function-like macro, so it can accept hashtable name, structure and other definitions.
This way is commonly used by Linux kernel, which tends to be fast. Note, that operations like hash_add, hash_for_each_possible are macros too.
Wrap hashtable into your own structure. Into the same structure you need to add all additional information about hash elements: size (for kmalloc), getter of the key from the element (for search) and setter for it(for inserter), and so on.
Something like
struct my_hashtable {
DECLARE_HASHTABLE(count, 7);
size_t obj_size;
unsigned long (*get_key)(void* obj);
void (*set_key)(void* obj, unsigned long key);
};

Casting void pointer

I have a struct
struct GROUP_POINTS
{
unsigned char number_of_points;
void *points;
};
struct GROUP_POINTS group_points;
The reason for points being a void pointer is that I want to keep the groups as general as possible, and setting the "link" to the correct struct at runtime.
One of the other structs is:
struct POINT_A
{
unsigned char something;
};
I can make another pointer that points to the *points to get access to the struct like :
struct POINT_A *point_a = (struct POINT_A *)group_points.points;
and then access the points by doing :
(*point_a).number_of_points = 5;
But I would really like to be able to use it like this:
group_points.points.number_of_points
So not needing the second pointer just to point to the void pointer. Is there any way to do this ?
Assuming the language is C++, you may want to consider template solution like that:
template <class T>
struct GROUP_POINTS
{
unsigned char number_of_points;
T *points;
};
typedef GROUP_POINTS<unsigned char> POINT_A;
//another typedefs for another points.
Also, you probably would be fine with just std::vector<T> instead of whole points structs, but just to illustrate general approach this is how it can be done.
Since all you need is to avoid using another pointer, you can use it like this:
((struct POINT_A *)group_points).points.number_of_points = 5;
Note that the type cast has a lower precedence than that of the . operator, the parenthesis is necessary.

Pass double pointer in a struct to CUDA

I've got the following struct:
struct Param
{
double** K_RP;
};
And I wanna perform the following operations on "K_RP" in CUDA
__global__ void Test( struct Param prop)
{
int ix = threadIdx.x;
int iy = threadIdx.y;
prop.K_RP[ix][iy]=2.0;
}
If "prop" has the following form, how should I do my "cudaMalloc" and "cudaMemcpy" operations?
int main( )
{
Param prop;
Param cuda_prop;
prop.K_RP=alloc2D(Imax,Jmax);
//cudaMalloc cuda_prop ?
//cudaMemcpyH2D prop to cuda_prop ?
Test<<< (1,1), (Imax,Jmax)>>> ( cuda_prop);
//cudaMemcpyD2H cuda_prop to prop ?
return (0);
}
Questions like this get asked from time to time. If you search on the cuda tag, you'll find a variety of examples with answers. Here's one example.
In general, dynamically allocated data contained within structures or other objects requires special handling. This question/answer explains why and how to do it for the single pointer (*) case.
Handling double pointers (**) is difficult enough that most people would recommend "flattening" the storage so that it can be handled by reference with a single pointer (*). If you really want to see how the double pointer (**) method works, review this question/answer. It's not trivial.

CLI/C++: void* to System::Object

This is a similar question to this SO post, which I have been unable to use to solve my problem. I have included some code here, which will hopefully help someone to bring home the message that the other posting was getting at.
I want to write a CLI/C++ method that can take a void pointer as a parameter and return the managed object (whose type I know) that it points to. I have a managed struct:
public ref struct ManagedStruct { double a; double b;};
The method I am trying to write, which takes a void pointer to the managed struct as a parameter and returns the struct.
ManagedStruct^ VoidPointerToObject(void* data)
{
Object^ result = Marshal::PtrToStructure(IntPtr(data), Object::typeid);
return (ManagedStruct^)result;
}
The method is called here:
int main(array<System::String ^> ^args)
{
// The instance of the managed type is created:
ManagedStruct^ myData = gcnew ManagedStruct();
myData->a = 1; myData->b = 2;
// Suppose there was a void pointer that pointed to this managed struct
void* voidPtr = &myData;
//A method to return the original struct from the void pointer
Object^ result = VoidPointerToObject(voidPtr);
return 0;
}
It crashes in the VoidPointerToObject method on calling PtrToStructure , with the error: The specified structure must be blittable or have layout information
I know this is an odd thing to do, but it is a situation I have encountered a few times, especially when unmanaged code makes a callback to managed code and passes a void* as a parameter.
(original explanation below)
If you need to pass a managed handle as a void* through native code, you should use
void* voidPtr = GCHandle::ToIntPtr(GCHandle::Alloc(o)).ToPointer();
// ...
GCHandle h = GCHandle::FromIntPtr(IntPtr(voidPtr));
Object^ result = h.Target;
h.Free();
(or use the C++/CLI helper class gcroot)
Marshal::PtrToStructure works on value types.
In C++/CLI, that means value class or value struct. You are using ref struct, which is a reference type despite use of the keyword struct.
A related problem:
void* voidPtr = &myData;
doesn't point to the object, it points to the handle.
In order to create a native pointer to data on the managed heap, you need to use pinning. For this reason, conversion between void* and Object^ isn't as useful as first glance suggests.

Resources