Как сбросить статические переменные в функции

есть ли способ, чтобы сбросить переменные, объявленные как static внутри функции? Цель состоит в том, чтобы убедиться, что функция не вызывается с задерживающимися значениями из несвязанного вызова. Например, у меня есть функция opearting на столбцах матрицы.

int foo(matrix *A, int colnum, int rownum){
static int whichColumn;
static int *v; //vector of length A->nrows 
   if (column != whichColumn){
    memset(v,0,size);
    whichColumn = which;
   } 
   //do other things
}

функция вызывается n раз, один раз для каждого столбца. Является ли это правильным способом "переустановки" статической переменной? Существуют ли другие общие способы сброса статических переменных? Например, я хочу убедиться, что что если вызов выполняется с новой матрицей с возможно разными размерами, то вектор v изменяется и обнуляется и т. д. Кажется, самым простым способом может быть вызов функции с нулевым указателем:

int foo(matrix *A, int colnum, int rownum){
static int whichColumn;
static int *v; //vector of length A->nrows 
   if (A == NULL){
    FREE(v);
    whichColumn = 0;
   } 
   //do other things
}

5 ответов


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


вместо этого используйте функцию инициализатора idempotent и глобальные переменные.

например:

int foo;
int *m = NULL;

static void InitVars() {
    foo = 0;
    if (m != NULL) {
        free(m);
    }
    m = malloc(sizeof(int)*5);
    memset(m, 0, sizeof(int)*5);
}

если ваш инициализатор действительно идемпотентный, вы можете вызвать его снова, чтобы сбросить переменные.

если вы нужно это называется автоматически, используйте __attribute__((constructor)) (для GCC) вот так:

static void InitVars __attribute__((constructor)) ();

однако вы должны отметить, что если вам нужно это сделать, вы должны пересмотреть использование in-function static переменные и вместо использования переданные свежие, которые возвращаются / записываются и передаются последующим связанным вызовам.


один из подходов, который я видел, когда модуль C был импортирован в C++ , заключался в том, чтобы окружить весь модуль оболочкой класса и заменить все статические переменные внутри функций уникальными "глобальными" varaibles вне функций. Я не знаю никакого хорошего способа добиться подобного эффекта для проектов с несколькими исходными файлами, хотя я хотел бы знать, существует ли он. У меня есть встроенный системный код на C, который я моделирую, добавляя некоторые оболочки C++ в VS2005. Например, у меня Регистры ввода-вывода определены так, что что-то вроде TX1CON = 0x5C; будет переводиться во что-то вроде IOMAP(0x251).P = 0x5C; IOMAP-это свойство, которое отправит" запись 0x5C на адрес 0x251 " в программу аппаратного моделирования. Этот подход работает хорошо, но я не могу выполнить чистый сброс. Есть идеи?


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

extern unsigned long global_reset_count;

void do_something(int whatever)
{
  static ... this, that, the other, etc. ...;
  static unsigned long my_reset_count;

  if (my_reset_count != global_reset_count)
  {
    my_reset_count = global_reset_count;
    ... initialize this, that, the other, etc ...
  }  
}

в некоторых многопоточных контекстах, если инициализация статических переменных может зависеть от некоторых глобальных переменных, можно заменить "if " на" while"; в таком случае; память в таком случае могут также потребоваться барьеры, хотя точные требования будут варьироваться в зависимости от условий эксплуатации.

кроме того, альтернативный шаблон, который может быть полезен во встроенных системах, должен иметь modules_initialized глобальная переменная, которая получает значение 0 методом глобального сброса, а затем каждый модуль начинается с чего-то вроде:

  if (!atomic_bit_test_and_set32(&modules_initialized, FOOBOZZ_MODULE_ID))
  {
    ... Initialize module FOOBOZZ ...
  }

Это потребует, чтобы было не более 32 идентификаторов модулей, и потребует, чтобы они были уникальными почему-то выделены, но некоторые системы могут справиться с этим довольно хорошо. Например, компоновщик может позволить определить "раздел данных" из адреса 0-31 адресного пространства, независимого от любого другого; если каждый модуль объявляет однобайтовую переменную в пределах этого адресного пространства, компоновщик может генерировать соответствующие адреса для этих переменных.


вы можете построить свою функцию таким образом, что если вы вызовете ее с нулевыми параметрами, то она сбросит свои внутренние статические переменные

вот пример :

int foo(matrix *A = NULL, int colnum = 0, int rownum = 0)
{
   static int whichColumn;
   static int *v; //vector of length A->nrows 

   if (A == NULL){
    FREE(v);
    whichColumn = 0;
   } 
   //do other things
}

вы на самом деле просто должны вызвать функцию для сброса, как это:

foo();  // internal values would then be reset

убедитесь, что все ваши параметры функции имеют значения по умолчанию, если, например, вы передаете необязательный, то убедитесь, что он имеет = boost:: none в качестве значения по умолчанию