2016-10-19 7 views
6

私は巨大なレガシーコードベースのプロジェクトに取り組んでおり、古いCスタイルのコードから逃れるために、その一部を再設計しようとしています。結果データがvoid *として返されるのはなぜですか?

私は問題に遭遇し、説明する短いプログラムを用意しました。

私が使用している従来のインターフェースでは、結果データへのポインタをvoid *として渡す必要があり、これを変更する必要はありません。

この例のunique_ptrは、実際のコードベースで、データを処理するすべてのものがスマートポインタを使用してメモリを管理していることを示しています。

私の問題は、結果データが壊れてしまうことです(最後の出力行/ printPayloadの最後の呼び出しを参照)。最後はすべて0ですが、2番目と3番目の出力行で示されるように、void *に変換して戻っても問題はないようです。

一時ファイルに関連する問題ですか? 私はそれを得ることはありません...

私はこの種の問題があなたの中には関係があることを望みます。

#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); 
} 

出力:

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 
+0

あなたは 'targetData'を設定'doSomething'では、この変更は関数にローカルです。パラメータは参照でなければなりません。 –

+0

これは次のように単純化できます: 'void doSomething(Payload * src、Payload * dst){dst = src; } ' – melpomene

+0

@PankajDaga、それは一時的なものへの参照になるので動作しません。 – StoryTeller

答えて

8

targetDatadoSomethingからローカル変数です。アドレスを割り当てた後は、範囲外になります。

実際にmyResultに割り当てられることはありません。

3

コードでは、targetDataのパラメータはdoSomethingのローカル関数です(つまり、関数のスコープを終了すると変更が失われます)。ただし、*targetDataは、main関数で宣言された変数myResultを参照しています。

ので、次のコードは動作するはずです:

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); 
} 
+0

です。それはタイプミスでした。ソースを編集するつもりです。ありがとう。 –

+0

@JonathanWakelyはい、私はちょうど元のコードにできるだけ類似した機能を保ちたいと思っていました。ソースを編集するつもりです。 –

1

あなたが今までターゲットにソースデータをコピーし、それにtargetDataポインタポイントオブジェクトのみの変更はありません。

このような何かが働くだろう:スマートポインタを介してソースペイロードの所有権を取る

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

はおそらく悪い考えです - 呼び出し元のコードが正しく例外を処理するために書かれている場合、それはオブジェクトを削除しますエラーでは、スマートポインタは2回削除されることを意味します。例外を正しく処理するために呼び出しコードが書き込まれていない場合、例外をスローできないコードを書くのはスマートポインタでは役に立ちません。

(それはポインタ間のキャストだとして、あなたはstatic_castをを使用することができますが、ボイド*がとreinterpret_castは潜在的に危険な何かが起こっている他の開発者に伝えることができるので、私はreinterpret_castは好む。)

関連する問題