5

When we return from function, if return value is a pointer, it must be define as static. Is this true for heap memory allocated pointer (such as new/malloc pointers),too?

consider this example:

#include"stdio.h"
char * func()
{
    char * X=new char[10];
    X[0]='C';
    x[1]='\0';
    return X;//is it a good return from function?
}
main()
{
    char * A=func();
    puts(A);
    delete[] A;
}
eddie
  • 1,252
  • 3
  • 15
  • 20
MD128
  • 501
  • 4
  • 12
  • 1
    Instead of fiddling with the increment/decrement operators, why not simply do `*(X + 1) = '\0'; return X;`? – Some programmer dude Jun 10 '15 at 11:47
  • local/stack: gone. Heap - not gone. If instances created on the heap with 'new' were to be auto-deleted on function returns, there would be no way to extend the lifetime of objects beyond that of the function that created them. That would be crippling for many apps, eg. GUI frameworks. – Martin James Jun 10 '15 at 11:48
  • 3
    use a [`std::string`](http://en.cppreference.com/w/cpp/string/basic_string) and don't worry about it. – NathanOliver Jun 10 '15 at 11:50
  • @Joachim Pileborg: what is the simplicity criteria?if i think form 1 is more simple... – MD128 Jun 10 '15 at 16:43
  • 1
    Actually I would like to change my comment to `X[1] = '\0';` which is even simpler and much more clear. Same with the first assignment, `X[0]= 'C';`., it's much more clear. As for the simplicity bit, why do three operations (increment, assign, decrement) when two is enough (array indexing and assignment). And it's also one less source of an error. What if you added *two* characters? Then you need to decrement twice or return `X - 2`, which works but is not very clear or obvious. – Some programmer dude Jun 10 '15 at 17:05
  • "... a pointer that defined in function scope is not OK to be return" - this just does not make any sense. It is completely irrelevant where the pointer is defined: in function scope or anywhere else. What matters is *where the pointer points to*, i.e. the lifetime of the object pointed by that pointer. You need to get your terminology in order, since otherwise any explanations will only deepen your misconceptions. – AnT stands with Russia Jun 12 '15 at 01:24
  • @Joachin pileborg: questions is edited according to your explanation. – MD128 Jun 26 '15 at 08:22

5 Answers5

8

As others already pointed out, technically, the code is okay.
However, the real problem with the code is the function signature char * func(). It only specifies that it will return a pointer to a char. That pointer can be

  • a normal pointer to a char variable
  • a pointer to a char array
  • a pointer to a c-style string

The pointer can point to

  • static memory
  • heap-allocated memory that will be freed somewhere else
  • heap-allocated memory that you are suppose to free yourself.

There is no way of knowing what to do unless you want to trust the documentation or to investigate in possibly a lot of code (functions calling functions calling functions...).

This can be avoided by returning

  • a char
  • an std::string
  • a container
  • a smart pointer.

Manual memory management is hard to get right within a complete application and should never be your main concern, so it should be avoided and not hidden by functions returning pointers.

stefaanv
  • 14,072
  • 2
  • 31
  • 53
1

Besides the weird increment/decrement fiddling, the code is okay.

The variable X goes out of scope when the function returns, but that's only the actual variable and not what it points to.

Pointers are basically simple integers, whose contents just happens to be an address to somewhere in memory, and treated specially by the compiler. What happens when the function returns is that the contents of the variable X is copied before the variable goes out of scope. Then the copy of the contents (the actual memory address) is again copied, this time to the variable A in the calling function.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • for this code, in run time, let X=0xffff1234. after. 'new ' line , for example, could we derefrence. 0xffff1234 outside the block , without potentially hidden error? could we derefrence A? – MD128 Jun 10 '15 at 17:14
  • 1
    @alwaystudent That's how pointers work, when you return `X` in the function, and assign it to `A` in the calling function, then `A` will be the same value as `X` and point to the same memory. The lifetime of dynamically allocated memory is until it's explicitly deallocated. – Some programmer dude Jun 10 '15 at 17:17
1

C++ is not garbage collected. X in func() is not deallocated until the delete [] A statement in main().

The shenanigans with incrementing and decrementing X do not change that (unless they cause X to point outside the memory allocated with operator new, which would result in undefined behaviour).

Peter
  • 35,646
  • 4
  • 32
  • 74
1

when you allocate memory using new, it allocates memory from heap so there is no harm in returning its pointer from any other function.

to read more about new() you can go to this link. http://www.tutorialspoint.com/cplusplus/cpp_dynamic_memory.htm

ritzz.soni
  • 335
  • 1
  • 15
  • Thanks for usefull link,but the point is we left the (function) block and may be lose variable behavior even its memory allocation exist – MD128 Jun 10 '15 at 16:58
  • sorry but i didn't get what exactly you mean by variable behavior, you asked that can I return the pointer from function in this case. so as its memory is allocated from heap you can and you can use that pointer anywhere, it won't change. – ritzz.soni Jun 10 '15 at 17:15
1

Heap allocations are not destoyed until you do so. But it is better to deallocate the Memory where it was allocated (if possible). This can prevent Memory leaks. This could look like the following:

#include"stdio.h"
void func(char *X)
{
    //I also think it Looks better to use it as an array
    X[0]='C';
    X[1]='\0';
}
main()
{
    char * A=new char[10];    //Allocate here
    func(A);
    puts(A);
    delete[] A;               //Deallocate here
}
eddie
  • 1,252
  • 3
  • 15
  • 20
Thomas Sparber
  • 2,827
  • 2
  • 18
  • 34