Вернуть динамический массив в C ++

Мне нужно вернуть беззнаковое int * из функции. Приведенный ниже код будет скомпилирован, но во время выполнения на 64-разрядной машине с Windows произойдет сбой. Я знаю, что где-то делаю глупую ошибку, и может ли кто-нибудь указать мне на это. :п. Я также объявил функцию в моем заголовке, поэтому я знаю, что это не та ошибка.

Обратите внимание, что я подверг цензуре имена и номера переменных, потому что проблема, в которой находится эта функция, еще не для публичного выпуска.

Функция:

 unsigned int* convertTime(unsigned int inputInteger, unsigned short inputFrac) {
    unsigned int* output = new unsigned int[2];
    double messageTimeFraction = double(inputFrac) * 20e-6;

    output[1] = unsigned int(inputInteger + 2209032000);
    output[2] = unsigned int(messageTimeFraction * 2e32);

    return output; // Seconds
}

Выполнение:

unsigned int* timeStamp;
timeStamp = convertTime(inputInteger,inputFrac);

person Elpezmuerto    schedule 23.06.2010    source источник
comment
Обратите внимание, что приведение unsigned int(...) не является строго допустимым (Visual C ++ поддерживает его как расширение). Есть связанный, несколько технический вопрос по этому поводу. Вы можете просто использовать unsigned(...) или (unsigned int)(...).   -  person James McNellis    schedule 23.06.2010
comment
Надеюсь, вы вызываете delete [] для ptr, возвращаемого вашей функцией, иначе у вас будет утечка памяти ... еще лучше используйте структуру с двумя int в ней   -  person Patrick    schedule 23.06.2010
comment
Если я правильно помню свой C ++, unsigned (что-то) - это не приведение, а конструктор, создающий временный. Таким образом, приведенный код определенно не является C. Соответствующим приведением для C будет (unsigned long) (...), а для C ++ - static_cast ‹unsigned long› (...)   -  person Jens Gustedt    schedule 23.06.2010
comment
Я считаю, что int - это 32 бита в компиляции Visual C ++ для 64-битного приложения, поэтому unsigned int(inputFrac * 2e32) будет бессмысленным и почти наверняка равным 0. Это не должно вызывать сбой, но в любом случае это может быть ошибка. Кроме того, 2209032000 - бессмысленное магическое число, а messageTimeFraction не используется. Если это не полная функция, сообщите нам об этом.   -  person David Thornley    schedule 23.06.2010


Ответы (7)


Ну, для начала у вас есть output[1] и output[2]. В c / c ++ массивы имеют нулевой индекс, поэтому это должны быть: output[0] и output[1].

Но, раз уж вы спрашиваете о C ++ ... я призываю вас использовать std::vector или std::pair.

(Конечно, для удобства чтения вы можете просто использовать тривиальную структуру с полезными именами полей)

person Stephen    schedule 23.06.2010
comment
Поскольку вектор не подходит для представления данных, которые имеют два целочисленных поля, каждое из которых имеет определенное значение (секунды и дробное). - person Pete Kirkham; 23.06.2010
comment
@Pete: там, где используется динамический массив, std::vector всегда намного, намного лучше. Если std::vector неуместен (действительно, вероятно, это должен быть struct с двумя членами), то это и динамический массив. Так что вы должны прокомментировать вопрос. Ваш голос против этого ответа несправедлив и необоснован. - person sbi; 23.06.2010
comment
@sbi Прочтите код. Динамически выделяемый массив (он не меняет размер, поэтому он не является динамическим массивом) здесь не следует использовать, поэтому замена его вектором - не лучший совет. Поскольку он был отредактирован, чтобы рекомендовать структуру, я удалил -1. - person Pete Kirkham; 23.06.2010
comment
@Pete: Тогда вам следует голосовать против за каждый ответ, поскольку до сих пор никто не рекомендует не использовать динамический массив. В противном случае отрицательное голосование по второму лучшему совету будет неправильным. - person sbi; 23.06.2010
comment
@Pete Kirkham: Вот почему я сказал рассмотреть структуру или пару, передача выходных параметров - еще один вариант. По вашему мнению, также неуместно возвращать динамический массив из двух элементов ... за исключением того, что вам не нужно вызывать delete[] для вектора. - person Stephen; 23.06.2010
comment
@sbi другие ответы только объясняли, что вызывает неопределенное поведение, а не рекомендуют изменения на основе заголовка вопроса, а не его содержания. - person Pete Kirkham; 23.06.2010
comment
@Stephen Когда вы изменили свой ответ, сделав ту же рекомендацию, что и моя, я удалил голос против. - person Pete Kirkham; 23.06.2010
comment
@Pete: OP хотел массив - кто знает почему? Я предложил улучшение в этом направлении, а также альтернативу. Только OP знает, что подходит для его программы. Рекомендация вектора исходила из 'new int [2]', а ссылка на pair была строго по содержанию. Тем не менее, спасибо за отзыв, и я согласен с тем, что и массив, и вектор, вероятно, не подходят. - person Stephen; 23.06.2010
comment
@Pete: Спасибо, что удалили. Кстати, чтобы вы знали ... Я не читал ваш ответ перед добавлением ссылки на структуру. Мне всегда казалось неприятным, когда отрывки из моих ответов попадают в чужие сообщения. - person Stephen; 23.06.2010
comment
@Sbi Использование структуры было наиболее подходящим - person Elpezmuerto; 24.06.2010

Я знаю, что где-то совершаю глупую ошибку и может ли кто-нибудь указать мне на это

Конечно, и это не имеет ничего общего с темой Q:

output[2] = unsigned int(inputFrac * 2e32);

Правильные записи в output: [0] и [1] - вы индексируете вне допустимых пределов. Результатом является «неопределенное поведение» (например, наблюдаемый вами сбой).

person Alex Martelli    schedule 23.06.2010
comment
На самом деле это могло иметь какое-то отношение к теме вопроса. Код записывается в область памяти, которой не должно быть в бесплатном хранилище. В зависимости от того, как реализовано бесплатное хранилище, оно может перезаписывать что-то важное, что позже вызывает сбой. - person David Thornley; 23.06.2010
comment
@David, точно то же самое могло бы произойти, если бы короткий массив был размещен в стеке - компилятор должен точно разместить хранилище, записывая за пределы, вы можете перезаписать адрес возврата или что-то в этом роде ...! То есть неопределенное поведение, как и для динамически выделяемого массива. - person Alex Martelli; 23.06.2010
comment
Конечно, но вы сказали, что это не имеет отношения к теме. Вот против чего я возражал. Я предлагал возможный механизм, почему это могло вызвать сбой. - person David Thornley; 23.06.2010
comment
@David, поскольку запись в массив за пределами границ может вызвать сбои (и многие другие плохие вещи: неопределенное поведение!), Независимо от того, динамически ли распределен массив или нет, правильно сказать, что динамически выделяемый характер массива не имеет ничего общего с этим. Утверждение X может произойти так же вероятно, независимо от того, присутствует Y или нет, по обычной аристотелевской логике, эквивалентно утверждению, что присутствие Y не имеет ничего общего с происходящим X. - person Alex Martelli; 23.06.2010
comment
Ах, мои извинения, я неправильно прочитал вашу ссылку на тему Q. - person David Thornley; 23.06.2010

Индексы в массиве из 2 элементов: array [0] и array [1], поэтому измените их на:

output[0] = unsigned int(inputInteger + 2209032000);
output[1] = unsigned int(inputFrac * 2e32);
person Brendan Long    schedule 23.06.2010

используйте output[0] и output[1], массивы C / C ++ основаны на 0

person peterchen    schedule 23.06.2010

Массивы в C ++ начинаются с нуля, поэтому элементами вашего массива размером два являются output[0] и output[1]

Вы также можете захотеть вернуть что-то, что лучше представляет данные, которые вы возвращаете, например структуру с элементами секунды и дробные_секунды, а не создавать новый массив.

Также несколько странно то, что вы делаете - 2209032000 - это количество секунд за 70 лет, и результат умножения короткого замыкания на 2e32 приведет к переполнению размера unsigned int.

person Pete Kirkham    schedule 23.06.2010

Более обычный способ написать такие функции в стиле C - передать ссылку на переменную, которая будет установлена.

Для удобства вы возвращаете выходной буфер, чтобы функцию можно было легко использовать в выражении.

unsigned int* convertTime(unsigned int* output, unsigned int inputInteger, unsigned short inputFrac) {
  double messageTimeFraction = double(inputFrac) * 20e-6;

  output[0] = unsigned int(inputInteger + 2209032000);
  output[1] = unsigned int(inputFrac * 2e32);

  return output; // Seconds
}

// later
unsigned int seconds[2];
unsigned int* pseconds;
pseconds = convertTime(seconds,a,b);
person Chris Becke    schedule 23.06.2010

Я создал временную структуру для различных форматов и написал функции конвертера для обработки преобразований. Используя структуры, мне не нужно беспокоиться об утечках памяти и улучшенной читаемости. Кроме того, теперь код более масштабируем, чем использование динамических массивов, поскольку я могу добавлять больше полей и создавать новые форматы времени.

struct time{
    unsigned int timeInteger;
    unsigned int timeFraction;
}time_X, time_Y;

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

person Elpezmuerto    schedule 23.06.2010