Frage

I created a function that returns an error code (ErrCode enum) and pass two output parameters. But when I print the result of the function, I don't get the correct values in the array.

// .. 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 ..

The getTrimmedList function is like this:

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

where:

  • foo is an object that holds arrays of FooBar objects
  • foo.getListCount() returns the number of objects with type FOO_TYPE_1
  • FOO_TYPE_1 is the type of object we want to take/list
  • foo.getEntryByIndex() returns the ith FooBar object with type FOO_TYPE_1
  • bar.isDeleted is a flag that tells if bar is considered as 'deleted' or not

What's my error?

Edit:

Sorry, I copied a wrong line. I commented it above and put the correct line.

Edit 2

I don't have control over the returns of foo and bar. All their function returns are ErrCode and the outputs are passed through parameter.

War es hilfreich?

Lösung

Couple of questions before I can answer your post...

Where is "index" defined in: vList = (short*)realloc(index, sizeof(short)*total);

Are you leaking the memory associated with: short* list = new short [cnt];

Is it possible you have accidentally confused your pointers in memory allocation? In any case, here is an example to go from. You have a whole host of problems, but you should be able to use this as a guide to answer this question as it was originally asked.

WORKING EXAMPLE:

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

Andere Tipps

You have serious problems.

For starters, your function has only one output param as you use it: vCnt. vList you use as just a local variable.

realloc is called with some index that we kow nothing about, not likely good. It must be something got from malloc() or realloc().

The allocated memory in vList is leaked as soon as you exit getTrimmedList.

Where you call the function you pass the local lstArr array as first argument that is not used for anything. Then print the original, unchanged array, to bounds in cnt, while it has 0 size still -- behavior is undefined.

Even if you managed to pass that array by ref, you could not reassign it to a different value -- C-style arrays can't do that.

You better use std::vector that you can actually pass by reference and fill in the called function. eliminating the redundant size and importantly the mess with memory handling.

You should use std::vector instead of raw c-style arrays, and pass-by-reference using "&" instead of "*" here. Right now, you are not properly setting your out parameter (a pointer to an array would look like "short **arr_ptr" not "short *arr_ptr", if you want to be return a new array to your caller -- this API is highly error-prone, however, as you're finding out.)

Your getTrimmedList function, therefore, should have this signature:

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

Now you no longer require your "count" parameters, as well -- C++'s standard containers all have ways of querying the size of their contents.

C++11 also lets you be more specific about space requirements for ints, so if you're looking for a 16-bit "short", you probably want int16_t.

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

It may also be reasonable to avoid requiring your caller to create the "out" array, since we're using smarter containers here:

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

In this style, we would likely manage errors using exceptions rather than return-codes, however, so other things about your interface would evolve, as well, most likely.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top