tags:

views:

112

answers:

4
#include <iostream.h>
using namespace std;

class A {
public:
   virtual char* func()=0;
};

class B :public A {
public:
   void show() {
      char * a;
      a = func();
      cout << "The First Character of string is " << *a;
   }
   char * func();
};


char* B::func() {
   cout << "In B" << endl;
   char x[] = "String";
   return x;
}

int main() {
   B b;
   b.show();
}

The problem in this is that I am returing a local varibale pointer/reference. Currently it is char x[]="String", but when I use a pointer char *x="String", the result is "S" but when Array reference the output comes as (i)

+2  A: 

That is because, when B::func() the memory allocated for the x[] is released hence if you try to access that memory location afterwards you will get garbage values. But when you do char *x="String", the memory for the string "String" is most probably allocated only once from the read-only section of your process memory. This address is guaranteed to remain valid until the execution of your program. In that case, if you try to access the pointer variable it will work correctly. BTW, as a side note, you need to declare a virtual base class destructor.

Naveen
In C, string literals have static duration, so char *x = "String" implies that `x` points to the first character of such location. In which case, the output 'S' is guaranteed by the standard. I believe this should be the case with C++ too, but I am not sure.
Alok
ok..I am not sure about that. And I surely won't rely on it even if it is guaranteed as it is not intuitive.
Naveen
OK, found a reference. It's legal, and in fact I think it's pretty intuitive. YMMV of course. http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/6a306c2ebeeec021/d0ce746544dc6b8d
Alok
Thanks for the link, I edited accordingly.
Naveen
A: 

First off, figure out how to post code blocks. It's not hard, just indent them by four spaces.

Second, you should never return a pointer to a function-local variable. Because they're allocated on the stack, and all bets are off as regards to whether they're around after the function returns.

EDIT: This was written when the provided code was butchered and incomplete. My point doesn't apply to this particular case, but it's still important to know.

Anon.
+7  A: 

When you do something like:

char *f(){ return "static string"; }

You're returning the address of a string literal, but that string literal is not local to the function. Rather, it is statically allocated, so returning it gives well-defined results (i.e. the string continues to exist after the function exits, so it works).

When you (attempt to) return the address of an array of char like this:

char *f() { 
   char x[] = "automatically allocated space"; 
   return x; 
}

The compiler allocates space for x on the stack, then initializes it from a string literal to which you don't have direct access. What you're returning is the address of the memory in the stack, not the string literal itself -- so as soon as the function exits, that array ceases to exist, and you have no idea what else might be put at that address. Trying to use that address causes undefined behavior, which means anything can happen.

Jerry Coffin
+1, most clear answer so far. I am not sure if one should use the term "stack" to explain the second case. I would rather use "automatic storage duration" or something similar (you do use that, but there might not be any stack in a hypothetical machine running C++!).
Alok
@Alok:C++ requires a list-in, first-out data structure for function activation records. In other words, you always have some sort of stack, though on different hardware it might be implemented differently.
Jerry Coffin
Thanks for the information. This is different from C, then. (Sorry about the noise.)
Alok
@Alok: Not really different from C at all -- both require that function activations take place in a last-in, first-out fashion, whether it's directly supported by the hardware or not. A LIFO data structure is usually called a stack, regardless of how it's implemented.
Jerry Coffin
A: 

To try to be more precise: B::func() is returning a pointer to a hunk of memory that it used for a temporary array. There are absolutely no guarantees what is in that memory once the function returns. Either (1, simplest good practice ) the calling function can allocate memory and pass in a string buffer for the called function to use or (2) the called function needs to allocate a buffer and the calling function needs to later release it (but this requires a very disciplined approach by the developer of the calling function, and I'd never want to rely on that) or (3, probably really the best practice) the calling function can pass in some sort of smart pointer that will release its memory when it goes out of scope, and have the called function use that smart pointer to point to the memory it allocates.

Joe Mabel