Is it possible to use a C++ smart pointers together with C's malloc?
If you are using shared_ptr
or unique_ptr
, you can specify a custom deleter. For example,
struct free_delete
{
void operator()(void* x) { free(x); }
};
This can be used with shared_ptr
like so:
std::shared_ptr<int> sp((int*)malloc(sizeof(int)), free_delete());
If you are using unique_ptr
, the deleter is a part of the unique_ptr
's type, so the deleter needs to be specified as a template argument:
std::unique_ptr<int, free_delete> up((int*)malloc(sizeof(int)));
However, it is better to use exceptions correctly, rather than avoiding them, when writing C++, especially with respect to allocation failures. In most cases, you cannot successfully recover from an allocation failure in the function trying to do the allocation, so exceptions can help you to handle the error where you are actually capable of handling it.
How to use smart pointer from function that returns a raw pointer
It depends. Consider this example:
struct example {
~example() { std::cout << "bye\n"; }
};
example* some_lib_function_A(){
return new example;
}
The library returns you a raw pointer to a dynamically allocated object. That's not nice, and to avoid dealing with the raw owning pointer you can wrap some_lib_function_A
into a function that returns a smart pointer that manages the object.
However, the library might also do something along the line of this (just for the sake of the argument. It should rather return a reference):
example* some_lib_function_B() {
static example ex;
return &ex;
}
And in this case you cannot delete
the returned pointer without running into problems.
Complete example:
#include <memory>
#include <iostream>
struct example {
~example() { std::cout << "bye\n"; }
};
example* some_lib_function_A(){
return new example;
}
example* some_lib_function_B() {
static example ex;
return &ex;
}
template <typename F>
std::unique_ptr<example> wrap(F f){
std::unique_ptr<example> res;
res.reset(f());
return res;
}
int main() {
wrap(some_lib_function_A);
wrap(some_lib_function_B); // free(): invalid pointer
}
The first line in main
does what you would expect, but the second line causes undefined behavior. Thats the reason the linked answer says that it is bad to write a function along the line of:
std::unique_ptr<example> wrap_bad(example& ex) {
std::unique_ptr<example> res;
res.reset(&ex);
return res;
}
Because you cannot know if the example
passed to the function was dynamically allocated or not. The function is lying about what it does, because a function taking a reference has no business in dealing with lifetime of its parameter. It can be used correctly, but it has great potential to be used wrong.
You have to read the libraries documentation and find out what the library expects you to do with the pointer. Sometimes you must call some library function clean_up(ex)
for proper clean up, in which case you can wrap the library clean up function in a custom deleter.
Use C++ shared_ptr to wrap C struct with deleter
The pointer which is managed by shared_ptr
is not the same as original one - it's a copy of it. As a result, you create an object of std::shared_ptr
which manages null pointer.
When you later call func
on another copy of the same pointer, you change the value of original pointer, but the one managed by std::shared_ptr
remains unchanged, and remains to be null.
Since there is no way to change the value of pointer managed by shared_ptr
, the only way to solve this problem is to init your pointer before passing it over to std::shared_ptr
for management.
How should I use an array of pointers of structs in C in my code below?
Compiling gives these warnings:
$ gcc Main.c A.c B.c -o out
B.c:5:8: warning: expression result unused [-Wunused-value]
b->x;
~ ^
B.c:6:8: warning: expression result unused [-Wunused-value]
b->y;
~ ^
2 warnings generated.
That leads almost directly to changing B.c
to this:
#include "B.h"
B_ptr create_B(int x, int y) {
B_ptr b = (B_ptr)malloc(sizeof(B));
b->x = x;
b->y = y;
return b;
}
Then the output becomes:
$ ./out
x=1
y=2
x=2
y=3
x=3
y=4
x=4
y=5
x=5
y=6
x=6
y=7
x=7
y=8
x=8
y=9
x=9
y=10
x=10
y=11
malloc and freeing memory between threads in C
- malloc() and free() are not thread-safe functions. You need to protect the calls to those functions with a mutex.
- You need to protect all shared variables with a mutex as well. You can use the same one as you use for malloc/free, one per variable.
- You need to declare variables shared between several threads as
volatile
, to prevent dangerous optimizer bugs on some compilers. Note that this is no replacement for mutex guards. - Are the buffers arrays, or two-dimensional arrays (like arrays of C strings)? You have declared all buffers as potential two-dimensional arrays, but you never allocate the inner-most dimension.
- Never typecast the result of malloc in C. Read this and this.
free(bufferaction)
, notfree(&bufferaction)
.- Initialize all pointers to NULL explicitly. After free(), make sure to set the pointer to NULL. Before the memory is accessed by either thread, make sure to check the pointer against NULL.
C linked list - when to free allocated memory
How do I go about freeing memory which has been allocated via malloc, while also returning the data to the caller?
Overall, the general rule in C memory management is that it must always be clear where the responsibility lies for freeing every piece of dynamically allocated memory, and wherever it does lie, that code must take care to fulfill all such responsibilities without fail. In your case, the only reasonable place to put the responsibility for freeing the struct _list_cell_t
objects allocated for a given list is in the code that removes those objects from the list again (the pop
, shift
, and free
functions).
After you free each such object, however, you must not access it again, so you must first store the data
pointer you intend to return in a local variable. In fact, you already do this.
There are lots of ways to implement the details, but I suggest this paradigm:
- Store a pointer to the no-longer-needed
struct _list_cell_t
in a local variable. - Update the structure of the list to cut out that object.
- Store a pointer to the wanted data in a local variable.
- Free the unneeded
struct _list_cell_t
via the pointer recorded in step (1) - Return the data
Related Topics
Multiple Implicit Conversions on Custom Types Not Allowed
Std::Map Default Value for Build-In Type
Std::Vector of Std::Vectors Contiguity
Two Phase Name Lookup for C++ Templates - Why
How to Compile for Windows Xp with Visual Studio 2012
What Is C++ Version of Realloc(), to Allocate the New Buffer and Copy the Contents from the Old One
What Does "#Define Str(A) #A" Do
Why Does Nvcc Fails to Compile a Cuda File with Boost::Spirit
Using Maven for C/C++ Projects
What Is the Most Efficient Way to Display Decoded Video Frames in Qt
Initializing a C++ Std::Istringstream from an in Memory Buffer
What Exactly Is or Was the Purpose of C++ Function-Style Casts
Cast Vector<T> to Vector<Const T>
If I Want to Specialise Just One Method in a Template, How to Do It
Private Inheritance VS Composition:When to Use Which
Why Do Objects Returned from Bind Ignore Extra Arguments
What Is the Vtable Layout and Vtable Pointer Location in C++ Objects in Gcc 3.X and 4.X