Присвойте значение члену структуры, используя двойной указатель

У меня есть функция, которая принимает двойной указатель на структуру и присваивает значение. Однако я получаю «место записи нарушения доступа …» при попытке доступа к участнику member1,
Это мой код:

struct mystruct{
unsigned int member1;
void * data;
};

int main(){

mystruct **foo = new mystruct *;
bar(foo);

}

void bar(unsigned int val, mystruct ** foo)
{
(*foo)->member1 = val;
}

5

Решение

Вы только что создали новый указатель mystruct. Это означает:

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

Итак, что вы хотите:

Вы хотите указатель, который имеет действительный блок памяти для хранения адреса другого указателя, который указывает на допустимую область памяти, где находится (вероятно, действительный) mystruct Хранится в.

То, что вы делаете: вы запрашиваете область памяти, где вы МОЖЕТЕ (что вы даже не делаете) хранить poitner для другого указателя … и так далее.

так что вы должны сделать это:

mystruct **foo = new mystruct *;
*foo = new mystruct;
5

Другие решения

У меня есть функция, которая принимает двойной указатель

Это странно. Если вы можете, упростите его, чтобы взять ссылку:

void bar(unsigned int val, mystruct & foo) {
foo.member1 = val;
}

mystruct foo;
bar(42, foo);

Если у вас нет контроля над функцией, вам понадобится объект в конце указателя:

mystruct foo;
mystruct * pointless = &foo;
bar(42, &pointless);

Можно, конечно, возиться с new если вы действительно хотите; но это почти наверняка плохая идея.

Ваш код выделяет и пропускает указатель, но не инициализирует его, чтобы он указывал на действительный объект; поэтому разыменование дает неопределенное поведение.

4

Эта функция в стиле C:

void bar1(mystruct* foo) {
foo->member1 = val;
}

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

void bar(unsigned int val, mystruct ** foo) {
(*foo)->member1 = val;
}

принимает указатель на mystruct* (скорее всего) для того, чтобы изменить сам указатель, т.е. для того, чтобы изменения, внесенные в указатель быть видимым для вызывающего абонента и, таким образом, вероятно, должен использоваться следующим образом:

mystruct* foo = new mystruct;
bar(&foo);

… тем не менее, обычно разумно избегать динамического распределения, и указатели передачи должны быть скорее редкостью, чем обычной практикой. Предпочитайте объекты с автоматическим хранением длительности динамически распределенным и предпочитайте передачу по ссылке вместо передачи по указателю (когда это возможно).

3

Другие ответы — хороший совет. Но также, если у вас есть контроль над bar функция, и должны быть в состоянии изменить в bar на какой объект ваш mystruct * указатель указывает на (что, вероятно, является причиной того, что у вас есть двойной указатель в первую очередь), тогда самый чистый подход заключается в использовании следующей подписи для bar:

void bar(unsigned int val, mystruct * &foo);

Он передает указатель по ссылке, так что вы можете изменить объект, на который указывает указатель, без ущерба для читаемости кода, например:

int main()
{
mystruct * foo = new mystruct;
bar(42, foo);
}

void bar(unsigned int val, mystruct * &foo)
{
foo->member1 = val;
foo = new mystruct;
}

Полный сценарий использования без утечки памяти может быть:

int main()
{
// allocate dynamically a mystruct whose member1 is equal to 1.
mystruct * foo1 = new mystruct;
mystruct * foo2 = foo1;
foo1->member1 = 1;

// pass by reference foo1
bar(42, foo1);
// here, foo1->member1 == 42 and foo2->member1 == 10

// free memory
delete foo1; // the one allocated in bar()
delete foo2; // the one allocated in main()
}

void bar(unsigned int val, mystruct * &foo)
{
// modify the object allocated in main()
foo->member1 = 10;

// allocate dynamically a mystruct, store its address in foo
foo = new mystruct;
foo->member1 = val;
}
2
По вопросам рекламы [email protected]