1

エラー コード ( ErrCodeenum ) を返し、2 つの出力パラメーターを渡す関数を作成しました。しかし、関数の結果を出力すると、配列に正しい値が得られません。

// .. some codes here ..
ErrCode err;
short lstCnt;
short lstArr[] = {};
err = getTrimmedList(lstArr, &lstCnt);

// list returned array (for comparison)
for (int i=0; i<lstCnt; ++i)
 printf("lstArr[%3d] = %d", i, lstArr[i]);
// .. some codes here ..

getTrimmedList関数は次のようになります。

ErrCode getTrimmedList(short* vList, short* vCnt)
{
  short cnt;
  ErrCode err = foo.getListCount(FOO_TYPE_1, &cnt);
  if (NoError!=err) return err;

  short* list = new short [cnt];

  short total = 0;
  for (short i=0; i<cnt; ++i)
  {
    FooBar bar = foo.getEntryByIndex(FOO_TYPE_1, i);

    if (bar.isDeleted) continue;

    list[total] = i;
    ++total;
  }

  *vCnt = total;
  //vList = (short*)realloc(index, sizeof(short)*total);
  vList = (short*)malloc(sizeof(short)*total);
  memcpy(vList, list, sizeof(short)*total)

  // list returned array (for comparison)
  for (int i=0; i<lstCnt; ++i)
   printf("lstArr[%3d] = %d", i, lstArr[i]);

  return NoError;
}

どこ:

  • fooオブジェクトの配列を保持するFooBarオブジェクトです
  • foo.getListCount()タイプを持つオブジェクトの数を返しますFOO_TYPE_1
  • FOO_TYPE_1取得/リストしたいオブジェクトのタイプです
  • foo.getEntryByIndex()itype のthFooBarオブジェクトを返しますFOO_TYPE_1
  • bar.isDeletedbarが「削除済み」と見なされるかどうかを示すフラグです

私のエラーは何ですか?

編集:

すみません、間違った行をコピーしました。上でコメントして、正しい行を入れました。

編集 2

fooとのリターンを制御することはできませんbar。それらの関数の戻り値はすべてErrCode、出力はパラメーターを介して渡されます。

4

3 に答える 3

1

あなたの投稿に答える前にいくつか質問があります...

「インデックス」は次の場所で定義されています。 vList = (short*)realloc(index, sizeof(short)*total);

以下に関連するメモリをリークしていますか? short* list = new short [cnt];

メモリ割り当てでポインタを誤って混乱させた可能性はありますか? いずれにせよ、ここに例があります。たくさんの問題がありますが、最初に尋ねられたように、これをガイドとして使用して、この質問に答えることができるはずです.

作業例:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

int getTrimmedList(short** vList, short* vCnt);

int main ()
{
  // .. some codes here ..
  int err;
  short lstCnt;
  short *lstArr = NULL;
  err = getTrimmedList(&lstArr, &lstCnt);

  // list returned array (for comparison)
  for (int i=0; i<lstCnt; ++i)
    printf("lstArr[%3d] = %d\n", i, lstArr[i]);
  // .. some codes here ..

  return 0;
}

int getTrimmedList(short** vList, short* vCnt)
{
  short cnt = 5;
  short* list = new short [cnt];
  short* newList = NULL;

  short total = 0;
  list[0] = 0;
  list[1] = 3;
  list[2] = 4;
  list[3] = 6;
  total = 4;

  *vCnt = total;
  newList = (short*)realloc(*vList, sizeof(short)*total);
  if ( newList ) {
    memcpy(newList, list, sizeof(short)*total);
    *vList = newList;
  } else {
    memcpy(*vList, list, sizeof(short)*total);
  }

  delete list;

  return 0;
}
于 2013-06-27T02:07:35.837 に答える
1

あなたは深刻な問題を抱えています。

まず、関数を使用するときの出力パラメータは vCnt のみです。単なるローカル変数として使用する vList。

realloc はindex、私たちが何も知らないもので呼び出され、おそらく良くありません。malloc() または realloc() から取得したものでなければなりません。

vList に割り当てられたメモリは、getTrimmedList を終了するとすぐにリークされます。

関数を呼び出す場所では、何にも使用されない最初の引数としてローカルの lstArr 配列を渡します。次に、元の変更されていない配列を cnt の境界に出力しますが、サイズはまだ 0 ですが、動作は未定義です。

その配列を ref で渡すことができたとしても、それを別の値に再割り当てすることはできませんでした。C スタイルの配列ではそれができません。

実際に参照渡しできる std::vector を使用して、呼び出された関数を埋めることをお勧めします。冗長なサイズを排除し、重要なことにメモリ処理の混乱を排除します。

于 2013-06-27T02:08:18.683 に答える
0

生の C スタイル配列の代わりに std::vector を使用し、ここでは「*」の代わりに「&」を使用して参照渡しを使用する必要があります。現在、out パラメータを適切に設定していません (呼び出し元に新しい配列を返したい場合、配列へのポインタは「short *arr_ptr」ではなく「short **arr_ptr」のようになります。この API はただし、ご存知のように、非常にエラーが発生しやすいです。)

したがって、getTrimmedList 関数には次の署名が必要です。

ErrCode getTrimmedList(std::vector<short> &lst);

「count」パラメーターも不要になりました。C++ の標準コンテナーにはすべて、コンテンツのサイズを照会する方法があります。

C++11 では、int のスペース要件をより具体的にすることもできるため、16 ビットの "short" を探している場合は、おそらく int16_t が必要です。

ErrCode getTrimmedList(std::vector<int16_t> &lst);

ここではよりスマートなコンテナーを使用しているため、呼び出し元に "out" 配列を作成するよう要求しないことも合理的です。

std::vector<int16_t> getTrimmedList(); // not a reference in the return here

このスタイルでは、戻りコードではなく例外を使用してエラーを管理する可能性が高いため、インターフェイスに関する他のことも進化する可能性が高くなります。

于 2013-06-27T01:56:24.153 に答える