Does shared_ptr free memory allocated on the heap? - shared-ptr

So in my job I don't have access to the full std library because....just because (corporate nonsense reasons). I can't use unique_ptr but I have access to shared_ptr and I'm working with c++11. So...
I am using a pre-existing (internal) library function that gets data for me and returns it via a raw point (lets say uint8_t*). And I am want to store this data in my class as a shared_ptr.
According to Will a shared_ptr automatically free up memory?
and http://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/
it appears that if I allocate memory on the heap and store this in a shared_ptr, the smart pointer should deallocate the memory (of uint8_t* data) for me. Is this true? Any links to literature would help. Also, from these links it seems that I can't use make_shared because I am "adopting a raw pointer from somewhere else."
class myClass
{
public:
shared_ptr<uint8_t> iv_data;
// rest of class
};
other function scope
data_size = getDataSize(...); // legacy internal function
uint8_t* data = new uint8_t[data_size];
getData(data, data_size); // legacy internal function
myClass object;
object.iv_spd_data = std::shared_ptr<uint8_t>(l_spd_data);
// if scope ends here will I get a memory leak for not freeing data

Here is an example of using shared_ptr<> with an array type and custom deleter. I've added some print statements to show the flow through the program. Note you don't need to know the size allocated when deleting, just that the type is an array. Not deleting with delete[] for an allocated array is undefined behavior; that is why the custom deleter is required.
See it in action on ideone
#include <iostream>
#include <memory>
#include <cstdint>
using namespace std;
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
cout << "using delete[]" << endl;
delete[] p;
}
};
int8_t* allocate_func()
{
cout << "allocating array" << endl;
return new int8_t[10];
}
int main() {
int8_t *ptr = allocate_func();
cout << "creating smart pointer" << endl;
shared_ptr<int8_t> sptr(ptr, array_deleter<int8_t>());
cout << "exiting main" << endl;
return 0;
}

I suppose that line:
object.iv_spd_data = std::shared_ptr<uint8_t>(l_spd_data);
should be:
object.iv_data = std::shared_ptr<uint8_t>(l_spd_data);?
shared_ptr can share ownership of pointer with other shared_ptr objects. When the last of shared_ptr owning your pointer is destroyed, then your object to which pointer is pointing to is deleted.
With object.iv_data = std::shared_ptr<uint8_t>(l_spd_data); you are creating temporary shared_ptr and assigning it to object.iv_data. Actually you are sharing ownership on l_spd_data between object.iv_data and temporary shared_ptr. Since temporary shared_ptr is destroyed right after this statement, the only owner is now object.iv_data. When myClass object is destroyed, iv_data is destroyed and l_spd_data deleted.
So you will not get memory leak in this case.

Related

Returning multiple values from a function

After reading this article I understand the methods for returning multiple values using structs or pointers (the first two). However, after describing the third method (using a temp array), the author writes:
We should not use this approach as the variable information is not
passed to the caller function. For example, we’re using the array’s
index to retrieve the values of our variables. Also, note that we have
to allocate the array dynamically in a heap. If we use the static
array, it ceases to exist when we exit the function, and accessing it
inside the caller function will result in undefined behavior.
This is the code example the author provides:
#include <stdio.h>
#include <stdlib.h>
 
// Function to return multiple values using an array
int* initialize()
{
    // Important: Dynamically allocate memory
    int *temp = (int*) malloc(sizeof(int) * 3);
 
    *temp = 10;
    *(temp + 1) = 20;
    *(temp + 2) = 30;
 
    return temp;
}
 
// Return multiple values from a function in C
int main(void)
{
    int a, b, c;
 
    int *arr = initialize();
 
    a = arr[0];
    b = arr[1];
    c = arr[2];
 
    printf("a = %d, b = %d, c = %d", a, b, c);
 
    // free memory
 
    return 0;
}
I don't understand what the author means, because I tried this method in a small program I wrote and it seems to works just fine, i.e. I can access the returned array's elements in the caller function. Why is this not recommended?
The referenced text is unclear and confusing at best. At worst, outright wrong.
We should not use this approach as the variable information is not passed to the caller function.
It's unclear what "variable information" means here. The actual values is getting back to the caller so that's not the problem. Maybe "variable information" is supposed to mean something like "information about number of variables" but that's unclear.
For example, we’re using the array’s index to retrieve the values of our variables.
Yes, well, of cause... If the values are being sent back in a (dynamic allocated) array, we have to use array indexing to get them. That's obvious and not really a problem.
Also, note that we have to allocate the array dynamically in a heap.
Finally something clear and correct.
If we use the static array, it ceases to exist when we exit the function, and accessing it inside the caller function will result in undefined behavior.
Here it's very unclear what "the static array" refers to. There is no static array in the code. It seems to be refering to some code only available in the authors head...
If the author is thinking about code like:
int temp[3]; // Instead of malloc
then the author is correct. But... that's not a static array so ....
If the author is thinking about code like:
static int temp[3]; // Instead of malloc
then the author is wrong. Due to static this array can be accessed from the caller.
So again... very confusing...
To answer your question:
Why is this not recommended?
Well, some concerns could be:
Dynamic allocation is an expensive operation. So don't use it unless you have a good reason.
Returning dynamic allocated memory from function and relying on the caller to free it later on is a source of many memory leak bugs. So avoid doing that.
BUT...
Good pratice rules nearly always comes with exceptions.
For instance consider a function that returns a rather huge and unknown number of results. For such a function it can be fine to return a pointer to dynamic allocated memory. But you would also need to return the actual number of results. It could look like:
int foo(int ** a)
{
// Generate results and use code like
*a = malloc(.. a lot ..)
...
// Perhaps some realloc(.. even more ..)
...
return number_of_results; // or perhaps -1 on error
}
int * a;
int results = foo(&a);
if (results > 0)
{
....
for (int i=0; i < results; ++i)
{
// Do something with a[i]
...
}
....
free(a);
}
...
If we use the static array, it ceases to exist when we exit the
function, and accessing it inside the caller function will result in
undefined behavior.
It is rubbish. static automatic array will still exist after the function return. It is because such array has static storage duration The function will be not reentrant.
The author probably meant automatic storage duration array.
Undefined behaviour (UB):
int *foo(void)
{
int array[10];
/* ... */
return array;
}
No undefined behaviour:
int *bar(void)
{
static int array[10];
/* ... */
return array;
}

Preventing GCC from merging variables in braced groups

Edit:
Apparently accessing variables inside braced groups after they end is undefined behaviour. Since I don't want to use dynamic allocation for nodes (as suggested by #dbush, #ikegami) I assume the next best way to keep hidden variables (within a function) is generating unique variable names for the nodes (with __LINE__) and 'declaring' without the use of a braced group. The code now reads something like
#define PASTE_(x, y) x ## y
#define PASTE(x, y) PASTE_(x, y)
#define LT_mark_(LABEL, NAME, DELETE)\
struct LifeTime LABEL ={\
.delete=DELETE,\
.prev=lt_head,\
.ref=NAME\
};\
\
lt_head = &LABEL;\
#define LT_mark(NAME, DELETE) LT_mark_(PASTE(lt_, __LINE__), NAME, DELETE)
/Edit
I'm trying to keep records for memory allocated within a function's scope.
Records are kept by a LifeTime structure, which form a linked list. This list is later traversed when returning from said function, in order to automatically free the memory. The lt_head variable is used to keep track of the current head of the list.
struct LifeTime {
void (*delete)(void*);
struct LifeTime *prev;
void *ref;
};
#define LT_mark(NAME, DELETE)\
{\
struct LifeTime _ ={\
.delete=DELETE,\
.prev=lt_head,\
.ref=NAME\
};\
\
lt_head = &_;\
}
int example (){
struct LifeTime *lt_head = NULL;
char *s = malloc(64); LT_mark(s, free);
char *s2 = malloc(64); LT_mark(s2, free);
...
}
Using this code, the temporary variables (named _) within the braced groups created by the LT_mark macro, are created with the same memory address.
I assume the reason for this is, as stated in the answer to this question: In C, do braces act as a stack frame?
that variables with non-overlapping usage lifetimes may be merged if the compiler deems it appropriate.
Is there any way to override this behaviour? I acknowledge it may be impossible (I am using GCC without any optimization flags, so I can't simply remove them), but the actual code I am working with requires that the variables inside these groups are kept afterwards, though hidden from visibility (as braced groups do usually). I considered using __attribute__((used)) but apparently this is only valid for functions and global variables.
The lifetime of a variable is that of its enclosing scope, so when that scope ends the variable no longer exits. Saving the address of that variable and attempting to use it when its lifetime has ended causes undefined behavior.
For example:
int *p;
{
int i=4;
p=&i;
printf("*p=%d\n", *p); // prints *p=4
}
printf("*p=%d\n", *p); // undefined behavior, p points to invalid memory
Inside of the braces, p points to valid memory and can be dereferenced. Outside of the braces p cannot be safely defererenced.
You'll need to do some dynamic allocation to create these structures. Also, this isn't a place where you should be using a macro instead of a function:
void LT_mark(void *p, void (*cleanup)(void *))
{
struct LifeTime *l = malloc(sizeof *l);
l->delete = cleanup;
l->prev = lt_head;
l->ref = p;
lt_head = l;
}
And similarly the cleanup function:
void LT_clean()
{
struct LiftTime *p;
while (lt_head) {
lt_head->delete(lt_head->ref);
p = lt_head->prev;
lt_head = lt_head->prev;
free(p);
}
}
Also, the prev field should be renamed to next, as the existing name is misleading.
Under most circumstances, you'll want to use #dbush's dynamic allocation solution. Since you're presumably using this with dynamic memory allocations of some kind anyway, dynamically allocating the descriptor blocks shouldn't be a huge overhead.
However, under some really restricted circumstances which you will have to police yourself, and assuming that you're not using an antediluvian version of the C compiler, it is possible to do this fairly simply with compound literals. Aside from the C compiler version limitation (C99 or better, which shouldn't be a huge burden), this will work in exactly the same circumstances as your edit#1 using token concatenation to generate a unique name: that is, if no use of the LT_mark macro is inside a braced-block subordinate to the function.
The reason for this restriction -- which, as I said, applies also to your solution with token concatenation -- is that the lifetime of automatic allocations terminates when control exits from the block in which they were declared. This is an essential aspect of C (and many other programming languages), so it's important to be clear about how it works.
Here's a simple example:
int example (){
struct LifeTime *lt_head = NULL;
char *s = malloc(64); LT_mark(s, free);
for (int i = 0; i < 4; ++i) {
/* InnerBlock */
char *s2 = malloc(64); LT_mark(s2, free);
....
}
/* Lifetime of all variables declared in InnerBlock expires */
....
/* If lt_head points to a struct automatically allocated inside
* InnerBlock, it is now a dangling pointer and cannot be used.
* The next statement is Undefined Behaviour.
*/
freeTheMallocs(lt_head);
}
Note that the problem is not that the inner block is executed more than once (although that will probably guarantee that you notice the problem). The same thing would happen had I written it as a conditional:
int example (int flag){
struct LifeTime *lt_head = NULL;
char *s = malloc(64); LT_mark(s, free);
if (flag) {
/* InnerBlock */
char *s2 = malloc(64); LT_mark(s2, free);
....
}
/* Lifetime of all variables declared in InnerBlock expires */
....
freeTheMallocs(lt_head); /* Dangling pointer */
}
The above cannot work with automatic allocation of descriptor blocks (but it will work fine with dynamic allocation).
OK, so what happens if you absolutely promise to only use LT_mark in the outermost block of your function, as with your original example:
int example (){
struct LifeTime *lt_head = NULL;
char *s = malloc(64); LT_mark(s, free);
char *s2 = malloc(64); LT_mark(s2, free);
freeTheMallocs(lt_head);
}
That will work. Your only problem is how to enforce the restriction, including on all the maintenance programmers who will modify the code after you leave the project, and may not have the foggiest idea of why they're not allowed to nest LT_mark inside a block (or even know that they're not allowed to do that).
But if you like playing with fire, you can do it like this:
#define LT_mark(NAME, DELETE) \
lt_head = &(struct LifeTime){ \
.delete=DELETE, \
.prev=lt_head, \
.ref=NAME \
}
This will work, in the limited set of cases in which it does work, because the the compound literal created by the macro "has automatic storage duration associated with the enclosing block." (§6.5.2.5/5).
Honestly, I sincerely hope you don't use the above code. I contribute this answer mostly in the hopes that it provides some kind of explanation of the importance of understanding lifetimes.

Is this code dereferencing a pointer or doing something else?

I've never seen this kind of thing before - I'm a little new to shared_ptr - is this a typical operation with a shared pointer, or is someone doing something a little fancy here? It doesn't seem like a dereference - it looks more like someone's trying to make sure the operator->() is defined...
I've done a google/duckduckgo on this in as many ways as I can think of, can't find any good examples online.
Thanks.
void fn(std::shared_ptr<int> data){
if(data.operator->() == NULL){
return; //this is an error
}
....//rest of function, doesn't matter
}
By
T* operator->() const noexcept;
you are accessing internal pointer of shared_ptr. If it is not NULL you can read data pointed by this pointer. To do it you must use:
T& operator*() const noexcept;
So when you want to check if shared_ptr points some data and read it, you could write:
void fn(std::shared_ptr<int> data) {
if(data.operator->() == NULL) // dereference pointer
return; //this is an error
int value = data.operator*(); // dereference data pointed by pointer
}
The code above is rather fancy way of using shared_ptr instances. Instead of calling operators like member functions - obj.operator #() you can use shorter form by applying #obj:
// this code does the same thing as above
void fn2(std::shared_ptr<int> data)
{
if(!data)
return; //this is an error
int value = *data;
std::cout << value << std::endl;
}
For more details, see reference.

Does move semantic unsuitable to the array in C++11?

I test the unique_ptr<> as follow
#include <iostream>
#include <memory>
using namespace std;
class A
{
public:
virtual ~A() {}
virtual void print()
{
cout << "A::Print()" << endl;
}
};
class B : public A
{
public:
virtual ~B() {}
virtual void print()
{
cout << "B::Print()" << endl;
}
};
int main()
{
A a;
B b;
A* arr[2] = {&a, &b};
arr[0]->print();
arr[1]->print();
unique_ptr<A*[]> ptr(move(arr));
/*
unique_ptr<A*[]> ptr(new A*[2]{&a, &b});
*/
ptr[0]->print();
ptr[1]->print();
return 0;
}
It get the result like (g++ 4.7.3)
A::Print()
B::Print()
A::Print()
B::Print()
Aborted (core dumped)
It seem like the ptr and arr point to the samething and when call
destructor, it has been deleted twice.
Why the move semantic don't take effect here?
Does it unsuitable to the array or it is about the unique_ptr?
The problem here is that unique_ptr<T> assumes that the object it manages was allocated with new. Since it is statically allocated on the stack instead, the unique_ptr destructor crashes when it tries to delete your array.
I'm not sure what you're trying to achieve with this unique_ptr anyways. Unique pointers make sure that the managed object is deleted at the end of the scope, but arrays allocated on the stack are deleted at the end of the scope, inherently. Would you have no unique_ptr, your code would function the same and not leak anyways.
The problem here is that you have no dynamically allocated memory here (never use the new keyword). So the unique_ptr is trying to free memory (call delete on) that was never allocated. My suggestion try to write simpler code, because you do a ton of things that are very unconventional.
You store A* for no reason, they will be delete automatically, I can't think of any good reason to store them as pointers
You don't use any standard library containers, you could use a std::array<A,2> instead of a c-style array
Also I'm guessing you just made this as a test so I can't really tell what your trying to achieve here

char* as an argument to a function in C

When passing a char* as an argument to a function, should the called function do a free on that string? Otherwise the data would be "lost" right and the program would leak data. Or are char* handled in a special way by the compiler to avoid everyone from having to do free all the time and automatically deletes it one it goes out of scope? I pass "the string" to the function so not an instance to an already existing char*. Or should one use char[] instead? Just feels so dumb to set a fixed limit to the argument input.
Keep this simple principle in mind: "always free memory at the same level that you allocated it". In other words a function should never try to free memory that it itself has not allocated. A short example to clarify this:
#include "graphics.h"
// The graphics API will get a Canvas object for us. This may be newly allocated
// or one from a pool of pre-allocated objects.
Canvas* canvas = graphics_get_canvas ();
// If draw_image () frees canvas, that violates the above principle.
// The behavior of the program will be unspecified. So, just draw the image
// and return.
draw_image (canvas);
// This is also a violation.
// free (canvas) ;
// The right thing to do is to give back the Canvas object to the graphics API
// so that it is freed at the same 'level' where it was allocated.
graphics_return_canvas (canvas);
Note that the function is not named graphics_free_canvas () or something like that, because the API may choose to free it or reuse it by returning it to a pool. The point is, it is an extremely bad programming practice to assume ownership of a resource that we did not create, unless we are specifically told otherwise.
It sounds like you're asking about this usage:
void foo(char* str);
foo("test string");
This is a special case; "test string" is a constant string stored in the string table within the executable, and doesn't need to be freed. foo should actually take a const char* to illustrate that, and allowing string literals to be stored in non-constant char*s is deprecated in C++
Whether the function should do a free or not depends on who owns the string. This code is perfectly valid and doesn't result in any memory leak:
int main()
{
char* s = malloc(.....);
f(s);
free(s);
}
The free can be performed inside function f as well if it takes the ownership of the string. However note that it is dangerous since you are assuming that string passed to function f is always allocated on heap using malloc or related functions. If a user passes pointer to a string allocated on stack your program will behave unpredicably.
On a general note, compiler doesn't do any special handling for memory management of strings. From compiler's point of view it is just a bunch of characters.
It seems that you are used to OOP style. I don't like the OOP, and for me it would be weird if I'd obtain a copy of an object after assigning. In this case the string is somewhere in memory, and its address is sent as char*, and not the whole string.
Also, be careful that you can free() only the pointers returned by malloc(), and only once.
Sometime a API expects a allocated buffer and its upto to the owner of the function which calls that api to free it.
myFunc()
{
char *error = malloc(<max size of error string>);
foo(error);
//Free the pointer here
free(error);
}
Some API like GLIB api's expect pointer to address of a declared variable
myFunc()
{
GError *error;
glib_api(&error);
if (error)
{
printf("Error %s", error-> message);
// can use glib API to free if error is NON NULL but message is allocated by GLIB API
g_error_free(error);
}
}
So even if you have not allocated memory to a variable you need to do the freeing while using standard libraries.
An allocated piece of memory, if not freed will result in lesser memory in a multiprocess environment, thereby degrading the performance of the system.
With plain char *, I would recommend always writing code with a policy that the caller "owns" the string and is responsible for freeing it if it was obtained by malloc. On the other hand, one could certainly envision "pseudo-pass by value" string objects in C, implemented as a struct, where policy dictates you have to relinquish ownership of a string (or duplicate it first and pass the duplicate) when passing strings as arguments. This could work especially well if the implementation used reference-counted storage for strings where the object passed was just a reference to the storage, so that the "duplicate" operation would merely be a reference-count increment plus trivial wrapper-struct allocation (or even pass-by-value struct).
The pointer to char as a function variable is an address to the same variable except where it's been substituted as a constant string. Your question can't be explained with a simple yes/no guideline; it depends on context. In the code below, a struct allocated on heap and stack individually are passed by reference as well as a string char * and data is inserted into the struct. Notice how the mallocs differ as to when they are used but the function works all the same.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// struct with all data within
typedef struct d
{
int number;
char name[50];
}data;
// struct with dynamic char *
typedef struct d2
{
int number;
char *name;
}dynamic_data;
// generic function placing data into struct
void InsertData ( data * out, int a, char * b )
{
out->number = a;
strcpy(out->name, b);
}
// generic function placing data into second struct
void InsertData2 ( dynamic_data * out, int a, char * b )
{
out->number = a;
strcpy(out->name, b);
}
int main ( void )
{
char * text = "some string\0";
int n = 20;
// allocated struct
data stuff;
dynamic_data stuff2;
dynamic_data * stuff3;
// need to allocate pointer within struct only
stuff2.name = (char *) malloc(50 * sizeof(char));
// heap allocated struct
stuff3 = (dynamic_data * ) malloc(50 * sizeof(dynamic_data));
// heap allocated sub element char *
stuff3->name = (char *) malloc(50 * sizeof(char));
// this is the data
printf ( "Pre insertion data\n" );
printf ( "s=[%s]\n", text );
printf ( "n=%d\n", n );
// this is the function insertting
InsertData ( &stuff, n, text );
printf ( "Post insertion data\n" );
printf ( "stuff.name=[%s]\n", stuff.name );
printf ( "stuff.number=%d\n", stuff.number );
// this is the function inserting
InsertData2 ( &stuff2, n, text );
printf ( "Post insertion data\n" );
printf ( "stuff.name=[%s]\n", stuff2.name );
printf ( "stuff.number=%d\n", stuff2.number );
//
// This is the segfault version - if nothing was allocated for pointers into
// this function scope, it would crash
// this is the function insertting under a heap allocated
InsertData2 ( stuff3, n, text );
printf ( "Post insertion data - dynamic version\n" );
printf ( "stuff3->name=[%s]\n", stuff3->name );
printf ( "stuff3->number=%d\n", stuff3->number );
// free in reverse order
free(stuff3->name);
free(stuff3);
free(stuff2.name);
return 0;
}

Resources