我有一个函数,它接受一个结构的双指针并赋值。但是,当我尝试访问成员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;
}
答案 0 :(得分:5)
您刚刚创建了一个新的mystruct指针。这意味着:
为您分配一个内存块,大小足以容纳一个地址,并将其分配给指向指向mystruct
成员的指针的指针。
这并不意味着,指针中有一个有效的地址保持,您希望指向mystruct
元素。甚至更多的是,甚至没有一个有效的地址,指向指针的指针指向,因为你只是为它分配了一个有效的存储区域,这并不意味着存储了一个有用的地址。
所以,你想要的是:
你想要一个具有有效内存块的指针来存储另一个指针的地址,该指针指向一个有效的内存区域,其中存储了一个(可能是有效的)mystruct
。
你正在做的是:你正在请求一个你可能存在的内存区域(你甚至没做什么)将一个poitner存储到另一个指针......等等。
所以你应该做的是:
mystruct **foo = new mystruct *;
*foo = new mystruct;
答案 1 :(得分:4)
我有一个带双指针的函数
这很奇怪。如果可以,请简化它以参考:
void bar(unsigned int val, mystruct & foo) {
foo.member1 = val;
}
mystruct foo;
bar(42, foo);
如果您无法控制该函数,那么您将需要指针跟踪末尾的对象:
mystruct foo;
mystruct * pointless = &foo;
bar(42, &pointless);
如果你真的想要的话,当然可以和new
混在一起;但这几乎肯定是一个坏主意。
您的代码分配并泄漏指针,但不会将其初始化为指向有效对象;所以取消引用它会产生不确定的行为。
答案 2 :(得分:3)
这个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 :(得分:2)
其他答案都是好建议。但是,如果您可以控制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;
}