Unable to cast from double* to vtkSmartPointer<double>

Hi,

Today I find a problem about casting a raw pointer to a SmartPointer. I’m actually randomly facing a segmentation fault when just simply allocating vector (which is very rare I guess) and I can’t figure out the reason. Then I decided to abandon all raw pointers in my code.

The current code is used to read the data from vtkDataset:

// The variable has 6 different data like velocity, salinity, etc.

vtkNew<vtkDataset> in_ds;
double* boxPoint_current_data = new double[6];

// I use memcpy() here because I find the program would crash sometimes if I use operaor"="
memcpy(boxPoint_current_data, in_ds->GetPointData()->GetTensors()->GetTuple(boxPoint_current_index),sizeof(double)*6);

// calculate arctan here
angle_current = atan2(boxPoint_current_data[2],boxPoint_current_data[1]);

I tried multiple ways from unique_ptr to vtkSmartPointer/vtkNew but none of them would work and try to get the return of GetTuple.

vtkSmartPointer<double>boxPoint_current_data;
boxPoint_current_data =  in_ds->GetPointData()->GetTensors()->GetTuple(boxPoint_current_index);

The biggest problem is that GetTuple return a double* while there is not a valid conversion from double* to vtkSmartPointer.

If I use unique_ptr, I have to define the variable either
auto boxPoint_current_data = make_unique<double>(6)
or
auto boxPoint_current_data = make_unique<double[]>(6)

If I use the first one, I think it would be difficult to access the boxPoint_current_data (honestly I don’t know how to do it for now). The latter one would meet a problem that unable to cast from double* to double[].

I would be appreciate if someone could help me sort it out.

vtkSmartPointer is only useful/usable for vtkObject-derived classes as far as I can tell - vtkSmartPointer helps with the reference counting done by the vtkObject.

What’s your intention behind trying to create a smart pointer to a double array? Do you intend to store the values and want them to be automatically be deleted at a later point?
Just for accessing the tuple values, this should be enough:

double const * values = in_ds->GetPointData()->GetTensors()->GetTuple(boxPoint_current_index);

Of course you need to take care that you don’t access values after in_ds has been deleted; if you require to hold on to the values, you can use GetTuple’s second variant, e.g. like this:

double * values = new double[6];
in_ds->GetPointData()->GetTensors()->GetTuple(boxPoint_current_index, values);

Yeah, this is what I’m exactly doing right now.

However, I really want to use the smart pointer instead of those raw pointer in my code, which could possibly help me avoid the segmentation fault. Do you have any idea about that?

In case you are using C++17, you can use a std::shared_ptr to a double [] (see this stackoverflow answer.

Otherwise, you can use an std::vector, see for example here. You’d have to resize the vector to the proper size, and then pass in the address of the first element, something like this:

std::vector t(6); // or `std::vector t; t.resize(6);
...->GetTensors(&t[0]);

I tried the shared_ptr before but it has the same problem with unique_ptr, which is:

auto boxPoint_current_data = make_unique<double[]>(6)

The latter one would meet a problem that unable to cast from double* to double.

On the other hand, the vector seems to be a good choice for this problem. Thanks for your help!

You don’t show how you would use the unique/shared_ptr to get the “unable to cast” problem; it should work, provided it is used correctly, something like

...->GetTuple(boxPoint_current_data.get());

(untested).

I used the shared_ptr in c++ 17 like this first:

.....
std::shared_ptr<double[]> boxPoint_current_data;
......
boxPoint_current_data = in_ds->GetPointData()->GetTensors()->GetTuple(boxPoint_current_index);

And this would gives me the problem about unable to cast.

Then I realize that I need the address of the pointer so I tried this one and get a lvalue problem.
boxPoint_current_data = in_ds->GetPointData()->GetTensors()->GetTuple(boxPoint_current_index);

After I check your code I find that I could use the your version and it works well. Thanks so much!