Is this code dereferencing a pointer or doing something else? - shared-ptr

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.

Related

Design Pattern to free an object in C

When programming in C, we usually create data structures that we initialize, then free when it is no longer needed. For instance, if we want to create a dynamic array of double, it is common to declare
struct vector {
double *data;
int size;
int capacity;
}
typedef struct vector vector;
vector *v_new(int n) {
vector *v = malloc(sizeof(vector));
v->data = malloc(n * sizeof(double));
v->size = n;
v->capacity = n;
return v;
}
The question is about the common patterns for a free function. In C, the function free accepts the NULL pointer and does nothing. Is it a common pattern to design v_free functions in such a way, or are they usually expecting a non-NULL pointer? To make it clear, would you expect this implementation
void v_free(vector *v) {
if (v != NULL) {
free(v->data);
}
free(v);
}
or this one ?
void v_free(vector *v) {
free(v->data);
free(v);
}
This question is asked because we began to teach C to undergraduate students in prep school in France, and we don't have that much experience in "C Design Patterns".
Thanks for your advice.
You can't access v->data if v is NULL. So if there is a chance of that, you must do the version which checks for that, which is better written as
void v_free(vector *v) {
if (v != NULL) {
free(v->data);
free(v);
}
}
If v should never be NULL here, it's perhaps better to add an assert to make the assumption explicit:
void v_free(vector *v) {
assert(v != NULL);
free(v->data);
free(v);
}
That way the programmer will notice they are doing something wrong.
Note that neither version detects a dangling pointer, ie. pointer which points to already destroyed object. This includes pointing to memory already freed (ie. you'd have double free here) or by pointer having pointed to local variable which is not in scope any more.
The question is about the common patterns for a free function. In C, the function free accepts the NULL pointer and does nothing. Is it a common pattern to design v_free functions in such a way, or are they usually expecting a non-NULL pointer?
This is going to be a matter of opinion.
My opinion is, unless you have a good reason otherwise, program defensively. Do the thing that will make debugging a mistake easier. Make v_free error on a null pointer. Something as simple as an assert.
void v_free(vector *v) {
assert(v != NULL);
free(v->data);
free(v);
}
Consider if we quietly ignore the null case. Did the caller intend to pass a null pointer, or was it a mistake? We don't know. If it was a mistake, the program continues merrily along and probably mysteriously crashes elsewhere. This makes debugging more difficult.
Consider if we assume v_free will always receive a non-null pointer. If it does free(v->data) is undefined behavior. At best a messy error, at worst the program continues merrily along and probably mysteriously crashes elsewhere. This makes debugging more difficult.
But if we provide an error, the mistake is stopped and revealed. Do the same thing for all your vector functions.
"But what if I want to pass a null pointer?" That should be infrequent, don't optimize for it. Make the caller do the check. If they really need to do it frequently, they can write a little wrapper function.
void v_free_null(vector *v) {
if( v == NULL ) {
return;
}
v_free(v);
}

I don't understand how pointers work in this code?

I don't understand this part of the code below. I mean alloc_MY_CAR() returns some array and how does & work so that newTab->pFunFree = &free_MY_CAR sees this array which newTab->pDat returns?
I don't understand pointers well. I only know that & store address of variable and * is a pointer or a value of the variable.
Could anyone guide me on how to use it properly and how does it work? I'm a beginner, so don't be so hard on me.
Thanks in advance!
#pragma once
struct MY_CAR {
char *model;
int year;
};
void print_MY_CAR(void* pdata);
void free_MY_CAR(void *pdata);
MY_CAR* alloc_MY_CAR();
switch (typ) {
case 0:
newTab->pDat = alloc_MY_CAR();
newTab->pFunFree = &free_MY_CAR;
newTab->pFunPrint = &print_MY_CAR;
break;
}
MY_CAR* alloc_MY_CAR() {
MY_CAR* tab = (MY_CAR*)calloc(1, sizeof(MY_CAR));
if (!tab) {
exit(0);
}
else {
char model[125];
printf("Podaj model: ");
scanf("%s", model);
tab->model = (char*)calloc(strlen(model) + 1, sizeof(char));
strcpy(tab->model, model);
printf("Podaj rok: ");
scanf_s("%d", &tab->year);
}
return tab;
}
void free_MY_CAR(void *pdata) {
MY_CAR* car = (MY_CAR*)pdata;
if (!car || !car->model) return ;
free(car->model);
free(car);
}
Notice that the function free_MY_CAR has an argument of type void*,
a pointer to a "void" type
(which is a C idiom for a pointer to something without telling the type of the thing pointed to),
and the first thing it does is to reinterpret that pointer as a pointer to a MY_CAR.
So the function is probably intended to be called like this:
newTab->pFunFree(newTab->pDat);
That is, the way the functions "know" what pointer was returned by
alloc_MY_CAR() and stored in newTab->pDat
is that the programmer explicitly tells the functions what pointer
is stored in newTab->pDat.
The advantage of doing such things is that it allows some code to do some operation on a data structure without necessarily having to know what kind of data structure it will actually operate on when the program actually runs.
In the call to pFunFree above, newTab could have been initialized by the case 0 code shown in the question, but there could be another case
that initializes it with alloc_MY_JOB(), &free_MY_JOB, and &print_MY_JOB,
where the MY_JOB functions allocate/free/print a data structure that is quite different from the data structure used by
alloc_MY_CAR(), &free_MY_CAR, and &print_MY_CAR.
Then if you call
newTab->pFunPrint(newTab->pDat);
we might not be able to predict when we write the code whether it will print the contents of a data structure created by
alloc_MY_CAR() or by alloc_MY_JOB();
but we can predict that it will print the detailed information it has
about your car, or your job, or whatever was read from the data file and stored in newTab.
The property that we can make a function call that uses a data structure in a way appropriate to that data structure, without having to know when we write the code what the type of data structure will be, is called
polymorphism.
This is a cumbersome idiom and there are lots of ways to get it wrong.
One of the selling points of C++ is to enable people to write polymorphic objects more easily than this.

Reset an element in a circular buffer

I was asked to implement a circular buffer that takes an unspecified type in C++. I assume the generic type to be of primitive type. (or should it consider non-primitive types?) For the buffer, I am using a basic array, e.g. T[] with new and delete to initialize and destroy it.
I have implemented the buffer class and tested it on integers with the expected output. But it does not work on std::string. The problem is that, when I pop the buffer, I clear the element by setting it to zero, and the compiler complains that doing so is ambiguous. As such, I need a generic way to clear an element, and I thought the std::array might support this feature, but I cannot find it in the documentation.
Is there a generic way to clear an element in a std::array or basic array, or is std::allocator my only option? Or, if I am completely in the wrong direction, How should I implement the pop method to reset the first element and increment the front index to that of the next element?
Thanks in advance!
In case it helps, below is my related code:
template<class T> T CircularBuffer<T>::pop_front()
{
if (_size == 0)
return 0;
T value = buffer[_front];
buffer[_front] = 0;
if (--_size == 0)
{
_front = -1;
_back = -1;
}
else
{
_front = (_front + 1) % _capacity;
}
return value;
}
In a circular buffer you do not really remove elements from memory, otherwise as Jagannath pointed out std::deque is your option. You more like "reset" the elements that have been popped.
buffer[_front] = 0;
means "assign 0 to a T". There are two methods that do that for T = std::string which explains the ambiguity. A bit simplified they look like this:
std::string std::string::operator=(char c);
std::string std::string::operator=(const char *cPtr);
I guess you don't want any of this, so my choice would be (as T.C. wrote):
buffer[_front] = T();
Additionally (and for a very similar reason)
if (_size == 0)
return 0;
is also a problem since it will crash, watch this:
std::string a = circularBuffer.pop_front(); // crashes on empty buffer
You could return T() here but the cleaner way would certainly be throwing an std::out_of_range exception.
One way you could do this, is by treating the memory as raw memory, and using placement new, and manual destructor call.
It could look something like this:
void push(const T& val)
{
new ( data + sizeof(T)*idx++ ) T { val };
}
void pop()
{
( (T*) (data + sizeof(T)*--idx) ) -> ~T();
}

How do you pass a struct Pointer in C?

I am a little confused by how pointers are passed in functions by reference?
For instance, here's some code that I have written
(I didn't copy the entire function, just the part of it that is relevant)
metadata * removeBlock(metadata *first)
{
metadata *temp = first;
if(first == NULL || first -> prev == NULL)
{
first -> in_use = 1;
first = NULL;
return temp;
}
}
What I want is that when the function returns, the original value passed in should be set to NULL.
Here is how I call the function, (this line of code will pull a metadata structure from a region in heap, it works correctly, I have debugged and made sure that after this, struct really points to a valid metadata struct)
metadata *strct = ((metadata *)ptr - sizeof(metadata));
removeBlock(strct);
However, after this method returns, strct is still the same value it was before I had passed it in the function. I tried passing in &strct, but that just threw an invalid cast exception. What is the best way to pass in the struct as an argument?
Thankyou.
I don't think what you want is a good design - if the user of your function wants the pointer set to null (why?) it would make sense to reset the value using the return value from your function.
Anyway, you'll want a pointer-to-a-pointer, like so:
metadata* removeBlock(metadata** first) {
metadata* temp = *first;
if( temp == NULL ) return temp;
if( temp->prev == NULL ) {
temp->in_use = true;
*first = NULL;
}
return temp;
}
metadata* strct = ((metadata*)ptr - sizeof(metadata));
removeBlock(&strct);
As #SheerFish said, all we have in C is pass-by-value. However, one can simulate pass-by-reference with a pointer.
void func(struct foo **fooptr) { *fooptr = 0; }
int main(int argc, char **argv) { struct foo *fooptr; func(&fooptr); }
This is passing a pointer ptr to the variable's value (never mind if that value was a pointer), allowing the function to play with the original value with *ptr. This technique is sometimes called pass-by-address, and is the closest C has to pass-by-reference.
If you pass by 'reference in C', you're going to need to keep in mind referencing and de referencing via ->/** and *. This bit of code I wrote may help you a bit
int delete_node(struct node** head, int target)
{
if(*head == NULL)
return 0;
if((*head)->data == target)
{
temp = *head;
*head = (*head)->next;
free(temp);
return 1;
}
}
Function call:
delete_node(&head, data)
You're working with direct memory pointer manipulation. You're tossing the location of the struct in memory, de referencing it, then changing the value at that memory location.
I didn't read all of the details, but this part jumped out as incorrect:
(metadata *)ptr - sizeof(metadata)
Pointer arithmetic is done in the units of the type, whereas sizeof gives you measurements in bytes.
So I suspect what you're trying to say is:
(metadata *)(((char*)ptr) - sizeof(metadata))
This is also making some assumptions about the machine you're running on, i.e. metadata may need to be padded to ensure that the fields are properly aligned for this use. If sizeof(metadata) is not a multiple of the word size, this will fail on a lot of architectures. (But x86 will let it slide, albeit with performance costs and some implications like atomic ops not working on the fields.)
pointers are passed by value. anything in c is passed by value. so in order to change the pointer passed to the function, it should receive metadata **first.
besides, you should use
metadata *strct = ((metadata *)ptr - 1);
as pointer arithmetic is done with multiples of sizeof(*p). so this is equivalent to
metadata *strct = ((metadata *)((char*)ptr - sizeof(metadata)));

Dangling pointers and double free

After some painful experiences, I understand the problem of dangling pointers and double free. I am seeking proper solutions.
aStruct has a number of fields including other arrays.
aStruct *A = NULL, *B = NULL;
A = (aStruct*) calloc(1, sizeof(sStruct));
B = A;
free_aStruct(A);
...
// Bunch of other code in various places.
...
free_aStruct(B);
Is there any way to write free_aStruct(X) so that free_aStruct(B) exits gracefully?
void free_aStruct(aStruct *X) {
if (X ! = NULL) {
if (X->a != NULL) { free(X->a); x->a = NULL; }
free(X); X = NULL;
}
}
Doing the above only sets A = NULL when free_aStruct(A); is called. B is now dangling.
How can this situation be avoided / remedied? Is reference counting the only viable solution? Or, are there other "defensive" approaches to freeing memory, to prevent free_aStruct(B); from exploding?
In plain C, the most important solution to this problem is discipline, because the root of the problem is here:
B = A;
Making a copy of the pointer without changing anything within your struct, circumventing whatever you use without any warning from the compiler. You have to use something like this:
B = getref_aStruct(A);
The next important thing is to keep track of the allocations. Some things that help are clean modularization, information hiding and DRY -- Don't Repeat Yourself. You directly call calloc() to allocate the memory while you use a free_aStruct() function to free it. Better use a create_aStruct() to allocate it. This keeps things centralized and in one place only, instead of throwing memory allocations all over your codebase.
This is a much better base for whatever memory tracking system you build on top of this.
I do not think you can do this automatically as C places the onus and burden of you to manage the memory and therefore your responsibility to ensure that references and of course dangling pointers are looked after!
void free_aStruct(aStruct *X){
if (X ! = NULL){
if (X->a != NULL){free(X->a); x->a = NULL;}
free(X); X = NULL;
}
}
By the way, there's a typo blip in the if check above ... use of lower case 'x' instead of 'X'...
My thinking when I was looking at the above code is that you are doing a free on a copy of a pointer variable of type aStruct *. I would modify it to be a call-by-reference instead...
void free_aStruct(aStruct **X){
if (*X ! = NULL){
if (*X->a != NULL){
free(*X->a);
*X->a = NULL;
}
free(*X);
*X = NULL;
}
}
And call it like this:
free_aStruct(&A);
Other than that, you are ultimately responsible for the 'dangling pointers' yourself whether its an unintentional coding or a design fault...
Even if you could prevent the free_aStruct(B) from blowing up, if there's any reference to B in the code behind your comment, that's going to be using memory that's been freed, and so might be overwritten with new data at any point. Just "fixing" the free call will only mask the underlying error.
There are techniques you can use but the bottom line is that nothing you do can be strictly enforcable in C. Instead, i recommend incorporating valgrind (or purify) in your development process. Also, some static code analyzers may be able to detect some of these problems.
Reference counting's really not that hard:
aStruct *astruct_getref(aStruct *m)
{
m->refs++;
return m;
}
aStruct *astruct_new(void)
{
sStruct *new = calloc(1, sizeof *new);
return astruct_getref(new);
}
void astruct_free(aStruct *m)
{
if (--m->refs == 0)
free(m);
}
(In a multithreaded environment you will also potentially need to add locking).
Then your code would be:
aStruct *A = NULL, *B = NULL;
A = astruct_new();
B = astruct_getref(A);
astruct_free(A);
...
//bunch of other code in various places.
...
astruct_free(B);
You've asked about locking. Unfortunately there's no one-size-fits-all answer when it comes to locking - it all depends on what access patterns you have in your application. There's no substitute for careful design and deep thoughts. (For example, if you can guarantee that no thread will be calling astruct_getref() or astruct_free() on another thread's aStruct, then the reference count doesn't need to be protected at all - the simple implementation above will suffice).
That said, the above primitives can easily be extended to support concurrent access to the astruct_getref() and astruct_free() functions:
aStruct *astruct_getref(aStruct *m)
{
mutex_lock(m->reflock);
m->refs++;
mutex_unlock(m->reflock);
return m;
}
aStruct *astruct_new(void)
{
sStruct *new = calloc(1, sizeof *new);
mutex_init(new->reflock);
return astruct_getref(new);
}
void astruct_free(aStruct *m)
{
int refs;
mutex_lock(m->reflock);
refs = --m->refs;
mutex_unlock(m->reflock);
if (refs == 0)
free(m);
}
...but note that any variables containing the pointers to the structs that are subject to concurrent access will need their own locking too (for example, if you have a global aStruct *foo that is concurrently accessed, it will need an accompanying foo_lock).

Resources