0

Right now I'm working with two functions across two .cpp files. Let's say I'm working with a struct called someStruct:

struct someStruct {
  int num;
}

A.cpp:

int main() {
  someStruct *a = NULL;
  bool ret;
  ret = foo(a);
  std::cout << a->num; // should print 5
}

B.cpp:

bool foo(someStruct *a) {
  someStruct *b = someFunction(); // points to an instance of someStruct on the stack
  // note that b->num should hold 5

  // need something here
  // ATTEMPT 1:
  a = new someStruct(*b);
  // ATTEMPT 2
  a = (someStruct *)malloc(sizeof(someStruct));
  a = memcpy(a, b, sizeof(someStruct));
}

What I want to accomplish is for a in the main function to end up pointing to an instance of someStruct that has the same values as the struct pointer b in foo().

Neither of the attempts I listed worked.

Santiago Varela
  • 2,199
  • 16
  • 22
Eric Zhang
  • 57
  • 1
  • 5
  • 4
    [Find a good beginners book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) and read about *references*. Optionally, don't declare a pointer to `someStruct` in the `main` function, and use the address-of operator when passing `a` to `foo`, and then use dereferencing and assignment in `foo` (as in `*a = *b`). – Some programmer dude Mar 30 '17 at 14:54
  • 3
    `someStruct *b = someFunction(); // points to an instance of someStruct on the stack` - this sounds like it's about to lead to *undefined behavior* (if your function allocated the `struct` locally its lifetime ends when the function returns) – UnholySheep Mar 30 '17 at 14:56
  • 5
    Don't use `malloc` in C++. – molbdnilo Mar 30 '17 at 14:58
  • 1
    `foo(a);` does not change the vlaue of `main()`'s `a`, which is a null pointer. `a->num` attempts to de-reference a null pointer. Without changing the `foo()` signature, changing its body will not help. – chux - Reinstate Monica Mar 30 '17 at 15:01
  • @chux how can I change `main()` 'a `a`? Can I change `foo()` to take a reference instead of a pointer? Will that change anything? – Eric Zhang Mar 30 '17 at 15:03
  • Either 1) make `a` in `foo(someStruct *a)` a reference variable, 2) return from the function `someStruct *` and assign `main's a` to that or 3) pass to `foo()` the address of `main's a` and change the function's signature. – chux - Reinstate Monica Mar 30 '17 at 15:05
  • You are passing a pointer in the foo() function, the contents of the a can change(e.x. a->num can be modified) but the point of the a can't change. You should change the definition of foo() from foo(someStruct *a) to foo(someStruct **a) and call it as foo(&a) – Stamatis Liatsos Mar 30 '17 at 15:06
  • @EricZhang Note that `foo()` presently does not return _anything_. Did you receive a compiler warning/error? – chux - Reinstate Monica Mar 30 '17 at 15:08
  • 1
    Just copy the entire object and don't bother with dynamic allocation and pointers. – Christian Hackl Mar 30 '17 at 15:22

1 Answers1

0

Terms: HEAP vs STACK

Your question should be named "how to create object copy". One reason is that original object location doesn't matter, creating copy from object on stack and from object on heap are pretty much the same. The second reason is that your current code tries copying object pointed by someFunction() return value which may have sense only if someFucntion() creted object on heap. Otherwise, if someFunction() created object on stack like this:

someStruct tmp;
tmp.num = 5; 
return &tmp;

then once someFunction() finishes execution, its stack frame is freed and might be reused for other functions stacks. Thus 'tmp' structure is located in memory, which can be overwritten any moment, so you can't rely on its data. Never use pointer to local variables after local variable goes out of scope.

Copying object

Well, your ATTEMPT 1 is fine. Using new for creating class or structure calls constructor to build object. You passed another object as parameter, so copy constructor is called. You didn't write copy constructor, but compiler created trivial one automatically, so it correctly copied all fields from original object to newly created.

However, cout didn't show expected output due to bug in another part of the program. Calling foo(a); means passing copy of a as a parameter to foo. So you don't change main's a value within foo, but change value of foo's copy of a. On return to main, a is still NULL and can't be dereferenced. As minimal fix, you need to pass a (which is already pointer, so it's a bit confusing) by pointer or by reference instead of passing it by value. Example:

int main() {
  someStruct *a = NULL;
  bool ret;
  ret = foo(&a);
  std::cout << a->num; // should print 5
  delete a;
  return ret;
}

bool foo(someStruct **x) {
  someStruct *b = someFunction(); // points to an instance of someStruct on the heap
  *x = new someStruct(*b);
  delete b;
  return true;
};

Make a good habit of calling delete eventually for each dynamically allocated buffer, memory leakages may become quite painful on larger programs.

nnovich-OK
  • 2,900
  • 2
  • 13
  • 16