Why is my result data being returned as void * is being violated?

I am working on a project with a huge outdated code base and trying to redo parts of it to get away from the old c-style code.

I ran into a problem and prepared a short program to explain.

The legacy interface that I use requires me to pass a pointer to the result data as void *, and I would like that to not change.

The unique_ptr in the example just shows that in my real code base, everything working on the data uses smart pointers to manage memory.

My problem is that the result data is broken (see the last output line / last call to printPayload); it's still 0 at the end, but it doesn't seem to be a problem with converting to void * and vice versa, as shown by the 2nd and 3rd output line.

Is this a temporary issue? I do not understand...

Hope this issue matters to some of you.

#include <iostream> #include <memory> struct Payload { long a; int b; int c; Payload() : a(), b(), c() {} Payload(long setA, int setB, int setC) : a(setA), b(setB), c(setC) {} }; void printPayload(const Payload& printThis) { std::cout << "payload -- a: " << printThis.a << " b: " << printThis.b << " c: " << printThis.c << std::endl; } void doSomething(Payload* sourceData, void* targetData) { if (!sourceData) return; std::unique_ptr<Payload> sourceDataUnique(sourceData); sourceDataUnique->a = 222; sourceDataUnique->b = 333; sourceDataUnique->c = 444; printPayload(*sourceDataUnique); targetData = reinterpret_cast<void*>(sourceDataUnique.release()); printPayload(*(reinterpret_cast<Payload*>(targetData))); } int main(void) { Payload* myPayload = new Payload(14, 8, 1982); Payload myResult; printPayload(*myPayload); doSomething(myPayload, &myResult); printPayload(myResult); } 

Output:

 payload -- a: 14 b: 8 c: 1982 payload -- a: 222 b: 333 c: 444 payload -- a: 222 b: 333 c: 444 payload -- a: 0 b: 0 c: 0 
+6
source share
3 answers

targetData is a local variable in doSomething . Once you assign an address to it, it goes beyond the scope.

You never assign myResult .

+8
source

In your code, the targetData parameter is local to the doSomething function (i.e., any change is lost after leaving the function scope). However, *targetData refers to the variable myResult declared in the main function.

So the following code should work:

 void doSomething(Payload* sourceData, void* targetData) { if (!sourceData) return; sourceData->a = 222; sourceData->b = 333; sourceData->c = 444; printPayload(*sourceData); Payload* td = static_cast<Payload*>(targetData); *td = *sourceData; printPayload(*td); } 
+3
source

You do not copy the source data of the target, but only change which object the targetData pointer points to.

Something like this will work:

 Payload* targetPayload = reinterpret_cast<Payload*>(targetData); *targetPayload = *sourceData; 

Obtaining ownership of the source payload using a smart pointer is probably a bad idea - if the calling code is written to handle exceptions correctly, then it will delete the object on error, so a smart pointer will mean that it will be deleted twice. If the calling code is not written right for handling exceptions, then it is your job to write code that cannot throw an exception that a smart pointer does not work with.

(since it is different between pointers, you can use static_cast, but I prefer reinterpret_cast, because void * can be anything, and reinterpret_cast tells other developers that something potentially dangerous is happening.)

+1
source

Source: https://habr.com/ru/post/1011465/


All Articles