0

To build nested TLV elements (e.g., 6F1A840E315041592E5359532E4444463031A5088801025F2D02656E), I'm using the following data structure:

typedef struct Element
{
    int16_t nTag; // Tells you if pValue points to a primitive value or constructed one 
    uint16_t nLength;
    void *pValue; // Could be either unsigned char* or TlvElement*
} TlvElement;

How can I implement a function that properly deallocates the memory used by the nested TLV elements?

// Let's build TLV data: 6F04A5020000
TlvElement *pTlvElement = (TlvElement*)malloc(sizeof(TlvElement));
pTlvElement->nTag = 0x6F;
pTlvElement->nLength = 4;
pTlvElement->pValue = malloc(sizeof(TlvElement)); // pValue points to another TLV element

TlvElement *pTlvElementChild = (TlvElement*)pTlvElement->pValue;
pTlvElementChild->nTag = 0xA5;
pTlvElementChild->nLength = 2;
pTlvElementChild->pValue = malloc(2 * sizeof(unsigned char)); // pValue points to a byte array
memset(pTlvElementChild->pValue, 0, 2);

Deallocate(pTlvElement);

//free(pTlvElementChild->pValue);
//free(pTlvElement->pValue);
//free(pTlvElement);
jpen
  • 2,129
  • 5
  • 32
  • 56

1 Answers1

0

You just deallocate it in the order you gave in the commented lines:

free((TlvElement *)(pTlvElement->pValue)->pValue);
free(pTlvElement->pValue);
free(pTlvElement);

The function free(void *) takes a void *, so the compiler wont complain. The only cast you need is to access the field pValue of the child element.

A word of caution: unless the tag already marks this, you might consider to add keep somewhere that the element does indeed contain a child element.

Assuming the value of ->nTag field can be used for this, you can deallocate the child elements recursively:

void Deallocate(TlvElement *e)
{
  if (e->nTag == 0x6f)
    Deallocate((TlvElement *)e->pValue);
  else
    free(e->pValue)
  free(e);
}

You might want to take precautions against endless recursion, though.

fork0
  • 3,401
  • 23
  • 23
  • @fork0-Thanks for your response but I want the Deallocate() function to be used for any TLV data deallocation (regardless of however nested/complicated that TLV data might be). I think what I'm not sure is how to traverse every single element. – jpen Aug 13 '12 at 19:42
  • @jpen: unless you provide this information in the element itself - you cannot. Can you say that by looking at nTag? – fork0 Aug 14 '12 at 07:03
  • @fork0-I've decided to use an arbitrary tree rather than dynamic array but thanks for your help anyway! – jpen Aug 14 '12 at 14:02