C: Возвращение пустоты против возврата двойного * из подфункции - PullRequest
6 голосов
/ 05 февраля 2010

Я пытаюсь ускорить некоторую общую обработку данных в C. Я написал несколько подпрограмм в виде:

double *do_something(double *arr_in, ...) {
   double *arr_out; 
   arr_out = malloc(...)

   for (...) {
     do the something on arr_in and put into arr_out
   }

   return arr_out; 
}

Мне нравится этот стиль, потому что его легко читать и использовать, но часто я называю его так:

 array = do_something(array,...);

Будет ли это быстрее кода (и, возможно, предотвратить утечки памяти), если бы вместо этого я использовал вместо void подфункции:

void do_something(double *arr_in, ...) {
   for (...) {
      arr_in = do that something;
   }
   return;
}

обновление 1: Я запустил valgrind --leak-check = full в исполняемом файле, и похоже, что при использовании первого метода не было утечек памяти. Тем не менее, исполняемый файл ссылается на библиотеку, которая содержит все подпрограммы, которые я сделал с помощью этой формы, поэтому он может не улавливать утечки из библиотеки.

Мне интересно, как бы я написал обертки для освобождения памяти и что на самом деле делает **, или что такое указатель на указатель, поэтому я избегаю использования маршрута ** (это и, возможно, Я сделал это неправильно, потому что он не компилируется на моем Mac).

Вот одна текущая подпрограмма:

double *cos_taper(double *arr_in, int npts)
{
int i;
double *arr_out;
double cos_taper[npts];
int M; 
M = floor( ((npts - 2) / 10) + .5);

arr_out = malloc(npts*sizeof(arr_out));

for (i=0; i<npts; i++) {
    if (i<M) {
        cos_taper[i] = .5 * (1-cos(i * PI / (M + 1)));
    }
    else if (i<npts - M - 2) {
        cos_taper[i] = 1;
    }
    else if (i<npts) {
        cos_taper[i] = .5 * (1-cos((npts - i - 1) * PI / (M + 1)));
    }
    arr_out[i] = arr_in[i] * cos_taper[i];
}
return arr_out;
}

Исходя из совета, который я получил здесь, звучит так, что лучшим методом будет:

void *cos_taper(double *arr_in, double *arr_out, int npts)
{
int i;
double cos_taper[npts];
int M; 
M = floor( ((npts - 2) / 10) + .5);

for (i=0; i<npts; i++) {
    if (i<M) {
        cos_taper[i] = .5 * (1-cos(i * PI / (M + 1)));
    }
    else if (i<npts - M - 2) {
        cos_taper[i] = 1;
    }
    else if (i<npts) {
        cos_taper[i] = .5 * (1-cos((npts - i - 1) * PI / (M + 1)));
    }
    arr_out[i] = arr_in[i] * cos_taper[i];
}
return
}

звоните:

int main() {
  int npts;
  double *data, *cos_tapered;

  data = malloc(sizeof(data) * npts);
  cos_tapered = malloc(sizeof(cos_tapered) * npts);

//fill data

  cos_taper(data, cos_tapered, npts);
  free(data);
  ...
  free(cos_tapered);
  ...
  return 0;
}

Ответы [ 12 ]

0 голосов
/ 05 февраля 2010

Вы бы сэкономили небольшое количество времени, не имея malloc, но это может быстро сложиться и существенно изменить ситуацию, если вы вызовете do_something в узком цикле.Вы бы также сэкономили небольшое количество времени, не возвращая double *, но опять же, это может сложиться, если do_something часто вызывается.

Что касается самой обработки, то не будет никакой разницы, поскольку оба случаяработают по двойному *

Так как вы не используете динамическое распределение памяти в предложенном вами методе, больше нет возможности утечек памяти.

0 голосов
/ 05 февраля 2010

В вашей функции

void do_something(double *arr_in, ...) {
   for (...) {
      arr_in = do_that_something;
   }
}

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

void do_something(double **arr_in, ...) {
   for (...) {
      *arr_in = do_that_something;
   }
}
/*
** Would be called like this:
** do_something(&array, ...);
*/

Придерживайтесь первого примера, так как его легче читать. Вам необходимо добавить проверку ошибок в первом примере, если вызов malloc не удался, и продолжить обработку с указателем NULL ...

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

...