Массив как выходной параметр в переполнении стека

Я создал функцию, которая возвращает код ошибки (ErrCode enum) и передать два выходных параметра. Но когда я печатаю результат функции, я не получаю правильные значения в массиве.

// .. 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() возвращает iго FooBar объект с типом FOO_TYPE_1
  • bar.isDeleted это флаг, который говорит, если bar считается удаленным или нет

В чем моя ошибка?

Редактировать:

Извините, я скопировал не ту строку. Я прокомментировал это выше и поставил правильную строку.

Редактировать 2

Я не могу контролировать возврат foo а также bar, Все их функции возвращаются ErrCode и выходы передаются через параметр.

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

Другие решения

У вас серьезные проблемы.

Для начала, ваша функция имеет только один выходной параметр, который вы используете: vCnt.
vList вы используете как локальную переменную.

realloc вызывается с некоторыми index что мы ничего не знаем, скорее всего, не хорошо. Это должно быть что-то полученное из malloc () или realloc ().

Выделенная память в vList просочится, как только вы выйдете из getTrimmedList.

Когда вы вызываете функцию, вы передаете локальный массив lstArr в качестве первого аргумента, который ни для чего не используется. Затем выведите исходный неизмененный массив до границ в cnt, пока он по-прежнему имеет нулевой размер — поведение не определено.

Даже если вам удалось передать этот массив по ссылке, вы не могли переназначить его на другое значение — массивы в стиле C не могут этого сделать.

Вам лучше использовать std :: vector, который вы можете фактически передать по ссылке и заполнить вызываемую функцию. устранение избыточного размера и, что важно, путаницы с обработкой памяти.

1

Вы должны использовать std :: vector вместо необработанных массивов в стиле c и передавать по ссылке, используя «&»вместо» * «здесь. Прямо сейчас вы неправильно устанавливаете свой параметр out (указатель на массив будет выглядеть как» short ** arr_ptr «, а не» short * arr_ptr «, если вы хотите вернуть новый массив для вашего абонента — однако, как вы выяснили, этот API очень подвержен ошибкам.)

Поэтому ваша функция getTrimmedList должна иметь следующую подпись:

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

Теперь вам больше не нужны ваши параметры «count», так как все стандартные контейнеры C ++ имеют возможность запрашивать размер их содержимого.

C ++ 11 также позволяет вам более точно определить требования к пространству для целых, поэтому, если вы ищете 16-битный «short», вам, вероятно, понадобится int16_t.

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

Также может быть разумно избегать требования вашего вызывающего к созданию массива «out», так как здесь мы используем более умные контейнеры:

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

В этом стиле мы, скорее всего, будем обрабатывать ошибки, используя исключения, а не коды возврата, однако, скорее всего, будут развиваться и другие аспекты вашего интерфейса.

0
По вопросам рекламы [email protected]