Frage

I have a function that takes a double pointer to a struct and assigns a value. However I get an "access violation writing location ..." when trying to access the member member1. This is my code:

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;
}
War es hilfreich?

Lösung

You just created a new mystruct pointer. That means:

You get allocated a memory block, large enough to hold a address, and assign it to the pointer which is pointing to a pointer that points to a mystruct member. That doesn't mean, that there is a valid address hold in the pointer which you expect to be pointing to a mystruct element. Even more currently there isn't even a valid address, where the pointer to the pointer is pointing on, as you just assigned a valid memory area to it, what doesn't mean there is a usefull address stored in.

So at all, what you want is:

You want a pointer which has a valid memory block to store a address in of another pointer, which is pointing to a valid memory area, where is a (probably valid) mystruct stored in.

What you are doing is: you are requesting a memory area where you COULD (what you aren't even doing) store a poitner to another pointer... and so on.

so what you should do is:

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

Andere Tipps

I have a function that takes a double pointer

That's weird. If you can, simplify it to take a reference:

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

mystruct foo;
bar(42, foo);

If you don't have control over the function, then you'll need an object at the end of the pointer trail:

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

You can, of course, mess around with new if you really want to; but that's almost certainly a bad idea.

Your code allocates and leaks a pointer, but doesn't initialise it to point to a valid object; so dereferencing it gives undefined behaviour.

This C-style function:

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

takes an argument of type mystruct* in order for changes made to object that foo points to to be visible to the caller. However this function:

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

takes pointer to mystruct* (most likely) in order to to modify the pointer itself, i.e. in order for changes made to the pointer to be visible to the caller and thus probably meant to be used this way:

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

... yet usually it is reasonable to avoid dynamic allocation and passing pointers should be rather rarity than a common practice. Prefer objects with automatic storage duration over the dynamically allocated ones and prefer passing by reference over passing by pointer (when possible).

The other answers are good advice. But also, if you have control over the bar function, and need to be able to change in bar to what object your mystruct * pointer points to (which is probably the reason why you have a double pointer in the first place), then the cleanest approach is to use the following signature for bar:

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

It passes by reference a pointer, so you are able to change to what object the pointer points to, without sacrificing readability of the code, for instance:

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

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

A complete usage scenario without memory leak could be:

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; 
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top