-4
//Smart pointer structure with built-in length and blocksize

typedef struct SMPTR_H_VAR
{
    UINT H_SMPTR_LEN;
    UINT H_SMPTR_BSZ;
} SMPTR_H_VAR;
typedef struct SMPTR
{
    void *MBLOC;
    SMPTR_H_VAR *shv;
    const UINT *const BLOCL;
    const UINT *const BLOCSZ;
} SMPTR;

//Smart pointer strucure 'constructor'
SMPTR *_SMPTRC(UINT var_sz, UINT var_num)
{
    /*            
    // SMPTR structure
    //
    // Memory block casted to void *
    // SMPTR_H_VAR structure
    // const UINT *const BLOCL variable, used as a reference length variable for the 'Memory block' above
    // const UINT *const BLOCSZ variable, used as a reference size variable, 'in bytes', for the size of the 'Memory block' above
    */

    //Creation and initialization is done dynamically, to prevent the rise of bad pointers.

    SMPTR *s = (SMPTR *)malloc(sizeof(SMPTR));
    SMPTR_H_VAR *shv = (SMPTR_H_VAR *)malloc(sizeof(SMPTR_H_VAR));

    //SMPTR_H_VAR variables are set through the SMPTR pointer
    s->shv;
    s->shv->H_SMPTR_LEN = var_num;
    s->shv->H_SMPTR_BSZ = var_sz * var_num;

    s->MBLOC = malloc(var_sz * var_num);
    s->BLOCL = &shv.H_SMPTR_LEN;
    s->BLOCSZ = &shv.H_SMPTR_BSZ;

    return s;
}

In this code, the SMPTR s is returned as a pointer, I want to return this variable as a non-pointer. Here I create a structure in dynamic memory, so that it will never go out of scope. That is why there are a lot of pointers everywhere.

vines
  • 5,160
  • 1
  • 27
  • 49
skrillac
  • 11
  • 1
  • 3
  • 4
    Why not just return the struct by value then? – The Paramagnetic Croissant May 26 '14 at 21:27
  • 3
    Also: [Don't cast the result of malloc (and friends)](http://stackoverflow.com/questions/605845). – Deduplicator May 26 '14 at 21:28
  • 2
    "I want to return this variable as a non-pointer." Because.... ? How about fixing this: `s->shv;` (which does nothing) by changing it to: `s->shv = shv;` before throwing in the towel on dynamic memory management. – WhozCraig May 26 '14 at 21:29
  • 1
    If you don't return it as a pointer, then you can simply return it by value, i.e. you don't need malloc at all. The downside is that a shallow copy of the entire structure is created whenever you pass it as a function parameter. But apart from that, I don't see a reason why you wouldn't allocate in on the heap and pass it around as a pointer, like you're doing now. – vgru May 26 '14 at 21:44

2 Answers2

0

Problems that I see when you return an object from your function.

  1. You have three calls to malloc in _SMPTRC. It's important that you figure out which code is responsible for freeing those memory. Otherwise, your code will be leaking memory.

  2. The calling functions will get a binary copy of the object. You'll have two SMPTR objects pointing to dynamically allocated memory (shv and MBLOC). You'll have to figure out a policy for freeing the memory they point to.

  3. The calling function will not be able to free the memory allocated in _SMPTRC for s. You'll have a memory leak. This can be easily resolved by using an object for s instead of a pointer which gets its memory from malloc.

They can be resolved if you figure out which block of code is responsible for feeing dynamically allocated memory. You just have to be cognizant of the problems.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Can you explain the 3rd point a bit? Why do you think it won't be possible to free the allocated memory? – vgru May 26 '14 at 21:55
  • @Groo The calling function will get a value of `*s` by copy. It won't get the pointer that `malloc` returned. – R Sahu May 26 '14 at 21:57
  • Got it, I thought you were talking about OP's snippet as posted above. – vgru May 26 '14 at 22:00
0

Your requirements are incompatible. If you return a struct by value, then the return value must have automatic storage duration. You must pick one of the two options.

Both of these setups are fine, you haven't provided enough details to indicate which would be better for your program though:

S foo(void)
{
     S s;
     s.field = 1;
     return s;
}

int main(void)
{
     S s = foo();
     printf("%d\n", s.field);
}

S *foo(void)
{
     S *s = malloc(sizeof *s);
     s->field = 1;
     return s;
}

int main(void)
{
     S *s_ptr = foo();
     printf("%d\n", s_ptr->field);
     free(s_ptr);
}
M.M
  • 138,810
  • 21
  • 208
  • 365