Выделение памяти для тройного указателя - PullRequest
0 голосов
/ 12 февраля 2009

Функция somefunction() принимает в качестве аргумента тройной указатель.

int somefunction(tchar ***returnErrors);

Как выделить память для параметра returnErrors?

Ответы [ 7 ]

2 голосов
/ 12 февраля 2009

Вы реализуете некоторую функцию или вызываете некоторую функцию?

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

tchar **theErrors = 0; // a vector of tchar vectors.
somefunction(&theErrors); 
if (theErrors) {
  // use the error values
  // free the memory somehow - this is for a null-terminated convention
      tchar **victim = theErrors;
      while (*victim) delete[](*victim++);
      delete[] theErrors;
}

Примечание: я использую 0 и удаляю [] вместо NULL и свободен, потому что в теге написано c ++.

2 голосов
/ 12 февраля 2009

На предположение. , .

Вы можете думать о returnErrors как о указателе на массив строк.

  1. Первый * подразумевает указатель на массив TCHAR (или единственная строка TCHARs)
  2. Второй * подразумевает указатель на массив строк.
  3. Последнее * так что вы можете изменить returnErrors и передать обратно новый память.

Чтобы отключить память для этого (глупый пример, выделение памяти внутри SomeFunction)

tchar ** errors;
// Oops it appears I need to pass back two error strings (+ 1 for null on end, so we know there are no more - thanks tlholaday)
errors = malloc(sizeof(tchar*) * 3);

// the first string has length 20 (+ 1 for null terminator)
errors[0] = malloc(sizeof(tchar) * 21);

// the second string has length 30 (+ 1 for null terminator)
errors[1] = malloc(sizeof(tchar) * 31);

// ensure the last is null
errors[2] = 0;

*returnErrors = errors;

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

1 голос
/ 12 февраля 2009

Кто-нибудь знает, как распределить память для параметра returnErrors?

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

tchar foo;
tchar * p_foo = &foo;
tchar ** pp_foo = &p_foo;
tchar *** ppp_foo = &pp_foo;
somefunction(ppp_foo);

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

Также обратите внимание:

  • Указатель никогда не является массивом. Это переменная, которая содержит значение адрес памяти или NULL.
  • Адрес, который содержит указатель не всегда соответствует начальный адрес массива. int ** р не всегда ссылается на начальный адрес int [] [].
  • Указатель, значение которого содержит начальный адрес массива не лучший способ передать этот массив как параметр функции. Вместо этого можно использовать ссылку на тип массива.
  • Массив, как правило, не лучший способ содержать набор связанных значений в C ++. std :: vector и другие контейнеры STL должны быть рассмотрены. (Однако ваш вопрос имеет два языка, C и C ++, в качестве тегов; конечно, это относится только к последней возможности. Почему два тега?)
1 голос
/ 12 февраля 2009

Зависит от того, что ожидает «какая-то функция». Вы должны расследовать это!

Может ожидаться указатель на массив фиксированного размера измерения 2 или обычный массив измерения 3, или ???

В случаях, о которых я упоминал, код может выглядеть как

tchar errors[SIZE1][SIZE2];
somefunction( &errors );

или

tchar errors[SIZE1][SIZE2][SIZE3];
somefunction( errors );
0 голосов
/ 12 февраля 2009

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

tchar **theErrors = 0; // a vector of tchar vectors.
int nErrors = somefunction(&theErrors); 
if (nErrors > 0) {
     for (int i = 0; i < nErrors; ++i)
     {
         printf(theErrors[i]);
         free(theErrors[i]);
     }
     free(theErrors);
}

Обратите внимание, что то, используете ли вы free или delete [], будет зависеть от того, как память была выделена в первую очередь.

0 голосов
/ 12 февраля 2009

Существует два варианта использования такой функции, как ваша someFunction (), которую я бы использовал.

Для инициализации:

{
    tchar **returnErrors;

    initErrors(tchar &returnErrors);
    /* now returnErrors has a place in memory*/
}

int initErrors(tchar ***returnErrors)
{
    *returnErrors = malloc(sizeof(tchar *) * SIZE1)

     for (i = 0; i < NUM_ELEMENTS; i++)
         (*returnErrors)[i] = malloc(sizeof(tchar) * SIZE2);

    /*add checks for malloc failures*/
}

Массив, передаваемый функции:

{
    returnErrors[SIZE1][SIZE2][SIZE3];

    someFunciton(returnErrors);
}

int someFunciton(tchar ***returnErrors)
{
    /*assuming that this is a valid index*/
    tchar x = returnErrors[1][1][1]; 
    /*return errors is used as a triple array*/
}
0 голосов
/ 12 февраля 2009

Тройной указатель не имеет смысла любой , если у вас еще нет конструкции этого типа. Я бы скорее рекомендовал использовать класс - или хотя бы стандартный контейнер. Но если вы должны знать, это так же просто, как

tchar ***pointer = (tchar***) malloc(sizeof(tchar**) * amount);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...