5

我有一个函数,它接受一个指向结构的双指针并分配一个值。但是,当我尝试访问成员时,我得到一个“访问冲突写入位置......” 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;
}
4

4 回答 4

5

您刚刚创建了一个新的 mystruct 指针。这意味着:

你被分配了一个足够大的内存块来保存一个地址,并将它分配给指向一个指向mystruct成员的指针的指针。这并不意味着,您希望指向一个mystruct元素的指针中有一个有效的地址。更当前甚至没有有效地址,指向指针的指针指向的位置,因为您刚刚为其分配了一个有效的内存区域,但这并不意味着其中存储了一个有用的地址。

所以,你想要的是:

您想要一个具有有效内存块的指针来存储另一个指针的地址,该指针指向一个有效的内存区域,其中mystruct存储了一个(可能有效的)。

你正在做的是:你正在请求一个内存区域,你可以(你甚至没有做)将一个指针存储到另一个指针......等等。

所以你应该做的是:

mystruct **foo = new mystruct *;
*foo = new mystruct;
于 2013-10-01T08:14:17.377 回答
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如果你真的想的话,你可以乱来;但这几乎可以肯定是个坏主意。

您的代码分配并泄漏了一个指针,但没有将其初始化为指向有效对象;所以取消引用它会给出未定义的行为。

于 2013-10-01T08:17:27.900 回答
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);

...但通常避免动态分配是合理的,并且传递指针应该比常见的做法更罕见。与动态分配的对象相比,更喜欢具有自动存储持续时间的对象,并且更喜欢通过引用传递而不是通过指针传递(如果可能)。

于 2013-10-01T08:18:30.933 回答
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; 
}
于 2013-10-01T09:01:22.800 回答