0

次のコードは、1 つの COM クライアントでは問題なく動作しましたが、新しいクライアント (同じソフトウェアの更新バージョン)string_array_to_bstr_safearray_variantではアクセス違反がスローされ、すべてが停止します。

私が以前に逃げていた何か間違ったことをしているかどうか、誰か教えてもらえますか..? メモリを適切に割り当てられていませんか?

#include "comutil.h"

void string_array_to_bstr_safearray_variant(long arraylength,char ** in_array,VARIANT *out_variant)
{
    CComSafeArray<BSTR> out_array;
    ATLENSURE_SUCCEEDED(out_array.Create(arraylength));
    for (int i=0;i<arraylength;i++)
        ATLENSURE_SUCCEEDED(out_array.SetAt(i,_com_util::ConvertStringToBSTR(in_array[i])));
    CComVariant ccv(out_array);
    HRESULT hr = ccv.Detach(out_variant);
    ATLENSURE_SUCCEEDED(hr);
}

//names: output parameter to contain variant holding safearray of bstrs
STDMETHODIMP CCalculation::get_output_shortnames(VARIANT* names)
{
    char** names_array = calc_get_short_output_names(calc); //this works fine
    string_array_to_bstr_safearray_variant(output_length,names_array,names); //this fails before returning
    return S_OK;
}

編集:デバッガ情報

デバッガーがないと、アクセス違反が発生します。

デバッガーでこのコードをステップ実行すると、動作しているように見えます。 output_length正しく設定されています。out_array作成され、正しく入力されているためout_variant、変数の監視を通じてわかる限りです。ただし、COM クライアントは依然として失敗し、次のように述べています"lisp value has no coercion to VARIANT with this type: #<safearray...>"(クライアントの以前のバージョンでは戻り値が適切に解釈されるため、これは奇妙です)。その後、メモリが不足していると不平を言ってクラッシュします。

デバッガー内でコードを実行しますが、ステップ実行ではなく実行させると、 のコンストラクター内で失敗し、CComVariantへの内部呼び出しが失敗したために無効な引数がスローされましSafeArrayCopyた。

編集:別の最近のステップスルーでは、ループで失敗したため、問題は @terriblememory が示唆するように CComSafeArray にあるのでしょうか?

4

2 に答える 2

1

さて、ついに私はこれに対する答えを見つけました!質問に投稿されたコードはそのまま正しいです。未定義の動作を引き起こす以前のコードがありました:

STDMETHODIMP CCalculation::configure(VARIANT radii) // radii contains a safearray of doubles
{
CComSafeArray<double> radii_sa;
radii_sa.Attach(radii.parray);
ULONG num_radii = radii_sa.GetCount();

//unpack radii array into c-style array
double *radii_array = new double[num_radii];
for (long i=0;i<num_radii;i++)
radii_array[i] = radii_sa.GetAt(i);

//...do something with radii_array...

delete[] radii_array;

return S_OK;
}

故意の間違いを見つけましたか?COMの規則によると、radiiは、私のdllではなく、クライアントによって所有されています。それに接続してからラッパーをスコープから外すことで、safearrayの割り当てを解除していました。returnステートメントの前にこれを追加することで修正されました:

radii_sa.Detach();
于 2012-06-21T13:31:59.523 に答える
1

CComSafeArrayのドキュメントには、実際にはBSTRをサポートするとは記載されていません。基盤となるSAFEARRAYでBSTRの機能フラグが設定されていますか?(これは実際には答えではありませんが、コメントするだけのカルマはありません、ごめんなさい!)

于 2012-05-09T02:03:36.150 に答える