1

I have a class Foo with a static factory method - Foo::createOne - that creates an instance and puts some data into a private member variable of type std:vector. When I call Foo::createOne, my program throws this exception: "EXC_BAD_ACCESS (Could not access memory)"

Here is the code:

Foo.h

#include <vector>

class Foo {
public:
    Foo();
    Foo(const Foo& orig);
    virtual ~Foo();

    static Foo * createOne();

private:
    std::vector<int> v;

};

Foo.cpp

#include "Foo.h"

Foo::Foo() {
};

Foo::Foo(const Foo& orig) {
};

Foo::~Foo() {
};

Foo * Foo::createOne() {
    Foo *f;
    f->v.push_back(5);
    return f;
}

main.cpp

#include <iostream>
#include "Foo.h"

int main(int argc, char** argv) {

    std::cout << "Testing createOne." << std::endl;
    Foo *myFoo = Foo::createOne();
    std::cout << "It worked." << std::endl;

}

Fixed one problem ...

Thanks for the answers. I fixed the uninitialized pointer problem (below). Now, I am getting a compiler warning "address of local variable 'f' returned"

Foo * Foo::createOne() {
    Foo f;
    f.v.push_back(5);
    return &f;
}
9
  • Foo *f; f->v.push_back(5); what do you think f points to? Commented Jun 10, 2013 at 20:53
  • That's not a "fix", you need to remove the asterisk in order for the fix to not create a new undefined behavior (returning a pointer to a local). Then of course you need to change your main. Commented Jun 10, 2013 at 21:05
  • What are you trying to do? Are you sure you need to return a pointer? Commented Jun 10, 2013 at 21:08
  • I'm trying to avoid having a copy of the "new Foo()" created when I return it. Maybe I'm confusing the function return for a function call the uses pass-by value. My understanding is that if I pass a class instance by value - doSomething(Foo f) - then doSomething gets a copy of f. I want doSomething to get a reference to f. But, I guess the correct way to do that is: doSomething(Foo& f). Thanks for the help I know Java well, but this is day 2 of C++ for me :-) Commented Jun 10, 2013 at 21:13
  • @MarkHansen If you know Java, then you should feel right at home with object pointers: objects of reference type in Java "map" to pointers in C++, complete with the need to assign new to them. A big difference is that if you use a variable unassigned in Java, the compiler treats it as an error; in C++ it's a warning. Another big difference is the need to call delete. Commented Jun 10, 2013 at 21:16

4 Answers 4

2
Foo *f;
f->v.push_back(5);

The first line is creating a raw, uninitialized pointer. It's not an instance of a variable, so attempting to dereference it is Undefined Behavior.

You need to initialize it to an instance, like this:

Foo *f = new Foo();
f->v.push_back(5);
// ...

delete f;

Only then will your code become valid.


Update: After reviewing your code once more I now realize that your use of pointers is totally unnecessary. You can do much the same by returning by value:

Foo Foo::createOne()
{
    Foo f;
    f.v.push_back(5);
    return f;
}

The reason you were getting the error address of local variable f returned was because you were returning a pointer to a temporary value. The local variable f will go out of memory when the function ends, and setting a pointer to it would be Undefined Behavior as well.

Sign up to request clarification or add additional context in comments.

7 Comments

Ah - I am a C++ rookie! So, I fixed that and this works, but compiler gives me a warning "address of local variable 'f' returned". How are factory methods done in C++?
@MarkHansen Oh, I forgot you were returning a pointer. You actually don't need a pointer in your example. Just return by value. I will update my post.
Thanks - so, why doesn't Foo f; go out of memory when the function ends?
@MarkHansen It does go out of memory. It's just that the compiler creates a copy of it when returning by value.
Ah! - that's what I want to avoid. How can the compiler create a copy of an arbitrarily complex "Foo" class?
|
2

You should create an instance of Foo before using it. On heap you can use following

Foo *f = new Foo();

Comments

1

You are de-referencing a pointer that has not been initialized:

Foo *f;  // f not pointing to a Foo instance
f->v.push_back(5);

That is undefined behaviour. You have to make f point to a valid Foo object.

Comments

1

In C++ when you declare a pointer, the constructor needs to be called manually, like this:

Foo * Foo::createOne() {
    Foo *f = new Foo; // <<=== Here
    f->v.push_back(5);
    return f;
}

This is different from objects defined as objects, not as pointers:

Foo Foo::createOne() {
    Foo f; // No initializer is necessary
    f.v.push_back(5);
    return f;
}

In this case the object is returned by value, so its content gets copied in the process.

When you create objects dynamically, the object pointed to by the pointer needs to be deleted in order to avoid memory leaks, like this:

int main(int argc, char** argv) {

    std::cout << "Testing createOne." << std::endl;
    Foo *myFoo = Foo::createOne();
    std::cout << "It worked." << std::endl;
    delete myFoo;

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.