Как выделить память для данного указателя на массив в C ++ - PullRequest
2 голосов
/ 14 декабря 2011

Я пытался выделить память следующим образом:

main:

X** a;
func(a);

func:

func(X** a){
   int size = 5;
   X* array = (X*)malloc(5*sizeof(X));
   //some writing to the array..
   a = &array;
}

При использовании отладчика я вижу, что когда я нахожусь в функции func все в порядке = я могу записать в массив, а a действительно указывает на массив, но в тот момент, когда я возвращаюсь к основному, я что-тоизменяется, и я не могу получить доступ к массиву через a (в отладчике он пишет что-то вроде: Target request failed: Cannot access memory at address 0x909090c3 и т. д.).

Где моя ошибка?

Примечание: этовыполняет компиляцию, но имеет проблемы во время выполнения при попытке доступа (например, к печати) к массиву в разделе main .

Спасибо.

Ответы [ 5 ]

7 голосов
/ 14 декабря 2011

Вы должны изменить свою основную часть следующим образом:

X* a;     // create an uninitialized pointer
func(&a); // pass the address of that pointer to the function

И внутри вашей функции сделайте это:

void func(X** a){
   int size = 5;
   X* array = (X*)malloc(5*sizeof(X));
   //some writing to the array..
   *a = array; // change the value of the pointer to point to the array
               // you allocated
}

Обратите внимание, что в C ++ можно было бы использовать std::vector<X>:

std::vector<X> func() {
    std::vector<X> buffer(5);
    // do stuff with buffer
    return buffer;
}

std::vector<X> foo = func();

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

3 голосов
/ 14 декабря 2011

Вы изменяете локальную копию своей переменной a, она не будет распространяться за пределы функции (т. Е. Область вызова). Самое простое решение вашей проблемы - передать a по ссылке, но вы также можете передать его, используя указатель и разыменовав указатель внутри вашей функции.

См. Приведенные ниже примеры.


Использование ссылки

void func (X*& a) {
  X* array = (X*) malloc (5*sizeof(X));

  a = array;
}

...

  X* a;

  func (a);

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

void func (X*& a) {

Использование указатель-указатель

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

После разыменования указатель на указатель мы можем безопасно хранить требуемую информацию.

void func (X** pointer_to_a) {
  X* array = (X*) malloc (5*sizeof(X));

  *pointer_to_a = array;
}

...

 X * a;

 func (&a); // pass in address of a

Примечание

Поскольку вы пишете C ++ (указывается в заголовке вопроса и теге), вам не следует использовать std::malloc, вместо этого обратитесь к operator new.

1 голос
/ 14 декабря 2011

В main, a - указатель на указатель. Это означает, что должны существовать две вещи: блок памяти и указатель на него. Тогда a может указывать на этот указатель. В вашей попытке этот средний указатель размещается в стеке func, а когда возвращается func, он уничтожается, так что это не сработает.

Вы можете сделать это:

X* pa;
X** a = &pa;
func(a);

func(X** a){
   int size = 5;
   X* array = (X*)malloc(5*sizeof(X));
   //some writing to the array..
   *a = array;
}
1 голос
/ 14 декабря 2011

Вы устанавливаете локальный указатель a на адрес локального указателя array, когда вы хотите установить для цели a значение array:

*a = array;

и назовите его как

X * a;
func(&a);

Возвращение указателя будет менее запутанным (т.е. X * func()).

Кроме того, вы пометили этот C ++, а не C, такне следует использовать malloc;используйте стандартные контейнеры или, если они у вас не работают, выделите с помощью new и управляйте памятью с помощью умного указателя.

0 голосов
/ 14 декабря 2011

Обдумайте это: a = & array;массив - это локальная переменная, размещенная в куче, и массив будет ненужным, когда его область действия будет превышена (тело функции).

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