Mykola Tetiuk
Mykola Tetiuk

Reputation: 375

Declaring a pointer inside a function, C++

What happens when I register a new pointer inside a function? I acknowledge, that the pointer's name should be destroyed. But what happens to the memory allocated? Will it be a memory leak? In my example, does the data object stay valid after the function is terminated, or it works just by chance, being prone to undefined behavior in more complicated instances? Where should be correct to place delete in this example? Or should this way of writing be avoided?

int * one (void);

int main (void){
    int *two = new int;
    *two = *one ();
    cout << "Address: " << one() << "|" << *one() << endl; // Address: 0xe51a78|5555
    cout << "Address: " << two << "|" << *two << endl;  // Address: 0xe519d8|5555
}

int * one (void){
    int * pFun = new int; // declaration of a pointer inside a function
    *pFun = 5555;
    return pFun;
}

Upvotes: 1

Views: 502

Answers (2)

Peter - Reinstate Monica
Peter - Reinstate Monica

Reputation: 16016

A dynamically allocated object exists until it is de-allocated, or "freed". That's exactly the purpose of dynamic allocation: Create objects whose life time does not depend on scope (that is, does not end at the next closing curly brace, like with automatic variables) but also is not infinite, like with global or static ones. Instead, the lifetime of dynamically allocated objects is entirely decided at run time, "dynamically".

Returning pointers to dynamically allocated objects is a common pattern, for example with factory functions.

Jacob is right that your program does not free the allocated object. It is good style to free all resources at some point before the program ends (this includes open files and sockets and other handles to system resources). But would that make any difference? No, because all operating systems clean up the memory after program termination (at the same time the linked answer makes the case for cleaning up anyway :-) ). Your program will run just fine as many times as you want, without exhausting the memory.

Upvotes: 3

Jacob Faib
Jacob Faib

Reputation: 1130

Your code as written will leak.

==365== Memcheck, a memory error detector
==365== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==365== Using Valgrind-3.17.0.GIT and LibVEX; rerun with -h for copyright info
==365== Command: ./test
==365== 
==365== 
==365== HEAP SUMMARY:
==365==     in use at exit: 8 bytes in 2 blocks
==365==   total heap usage: 3 allocs, 1 frees, 72,712 bytes allocated
==365== 
==365== 4 bytes in 1 blocks are definitely lost in loss record 1 of 2
==365==    at 0x484D103: operator new(unsigned long) (vg_replace_malloc.c:342)
==365==    by 0x10919E: main (in /petsc/test)
==365== 
==365== 4 bytes in 1 blocks are definitely lost in loss record 2 of 2
==365==    at 0x484D103: operator new(unsigned long) (vg_replace_malloc.c:342)
==365==    by 0x1091CC: one() (in /petsc/test)
==365==    by 0x1091A7: main (in /petsc/test)
==365== 
==365== LEAK SUMMARY:
==365==    definitely lost: 8 bytes in 2 blocks
==365==    indirectly lost: 0 bytes in 0 blocks
==365==      possibly lost: 0 bytes in 0 blocks
==365==    still reachable: 0 bytes in 0 blocks
==365==         suppressed: 0 bytes in 0 blocks
==365== 
==365== For lists of detected and suppressed errors, rerun with: -s
==365== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Note for the above I removed both printing calls, as the first one calls one() twice more, resulting in 2 additional leaks

You never directly store the pointer returned by one(), instead immediately de-reference it. This has the effect of throwing out that address. A better approach would be to do the following:

// two is an uninitialized pointer
int *two;
// Assign the returned pointer to two
two = one();
// Assign the value pointed to by two (and in effect one()) to three and use it
int three = *two;
functionThatExpectsAnInt(three);
// Alternatively use two directly, it points to valid memory whose value has not changed
functionThatExpectsAnInt(*two);
// Clean up resources from one()
delete two;

With functions that return allocated memory, the caller is the effective "owner" of the resources returned by the function. So the caller has to either free the resources, or pass them on to another function that will.

Upvotes: 3

Related Questions