3

I am trying to use a doubly linked list data structure to implement a replacement policy in a buffer manager.

But my C program doesn't have a linked list library so I just defined the data structure by myself.

The problem is: Can I avoid doing any [dynamic?] memory allocation to use a doubly linked list?

What's the advantage of using palloc() instead of malloc()?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
runcode
  • 3,533
  • 9
  • 35
  • 52
  • 1
    It is very hard to decipher what you are asking due to bad grammar. A doubly linked linked list is a data structure, which implies that it contains data and that data must reside within some allocated memory, but that memory can be allocated in any way, so malloc is not necessary. I doubt this answers your question though, since I have no idea what it is... – Andreas Vinter-Hviid Oct 20 '12 at 17:52
  • @RavindraBagale its storage pool based allocator, and not standard (at least not that I'm aware of). – WhozCraig Oct 20 '12 at 17:52
  • It's linked list so it should be dynamic .. but if you not allocate memory dynamically then how will you fit data as many as you want ? – Omkant Oct 20 '12 at 17:53

1 Answers1

5

You can certainly create a doubly-linked list without using dynamic memory allocation at all; it is just aconventional to do so.

#include <stdio.h>
#include <assert.h>
#include <inttypes.h>

enum { NODEBUG = 0, DEBUG = 1 };

static const int debug = NODEBUG;

typedef struct DList DList;
struct DList
{
    int    data;
    DList *next;
    DList *prev;
};

enum { MAX_DLIST = 100 };
struct DList dlist[MAX_DLIST];

static void add_node(DList *head, DList *node)
{
    assert(head != 0 && node != 0);
    if (head->next == 0)
    {
        assert(head->prev == 0);
        head->next = node;
        head->prev = node;
        node->next = head;
        node->prev = head;
    }
    else
    {
        assert(head->prev != 0);
        node->next = head->next;
        node->prev = head;
        head->next->prev = node;
        head->next = node;
    }
}

static void diagnode(DList *node)
{
    if (debug)
        printf(" (T = 0x%.12" PRIXPTR ", N = 0x%.12" PRIXPTR ", P = 0x%.12" PRIXPTR ")\n",
               (uintptr_t)node, (uintptr_t)node->next, (uintptr_t)node->prev);
}

static void print_list(DList *head)
{
    assert(head != 0);
    printf("List:");
    if (head->next != 0)
    {
        DList *node;
        int counter = 0;
        if (debug)
            printf("\nHEAD");
        diagnode(head);
        for (node = head->next; node != head; node = node->next)
        {
            printf(" %3d", node->data);
            diagnode(node);
            assert(counter++ < MAX_DLIST);
        }
    }
    printf(" <EOL>\n");
}

int main(void)
{
    DList head = { 0, 0, 0 };

    for (int i = 0; i < MAX_DLIST; i++)
    {
        dlist[i].data = (i * 13 + 7) % 100;
        add_node(&head, &dlist[i]);
        if (debug)
            print_list(&head);
    }
    print_list(&head);
}

Not a memory allocation in sight! You can use a variant of this when you have something like a buffer manager where there is a fixed array of data buffers, but you want an LRU (least-recently used) replacement policy. Instead of have the data directly in the doubly-linked list structure as in this example, the data element would point to an entry in the buffer pool. You can then add and remove entries from the list without changing anything in the main data structure that your list is linked to.


If palloc() is a pooled memory allocator, the advantage of using it over malloc() is that you can release all the memory allocated to a given pool with a single function call, rather than having to manage all the separate frees yourself. Sometimes, a pool allocator will be more efficient than separate memory allocation with malloc(); it might allocate a big array of a fixed size structure and then dole out entries on request, reducing the number of allocations and thereby reducing the amount of overhead.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • thankyou for your answer, i have no idea why other people give me negative scores.. is this a stupid question? – runcode Oct 21 '12 at 06:06
  • It's not a stupid question, though it is relatively unusual not to do dynamic memory allocation with linked lists. However, a buffer manager is one of the places where avoiding the overhead of repeated single item allocation by allocating an array (statically, as in my answer, or dynamically allocating the array all at once) and using that is perfectly reasonable. I suspect that the down-voters have not encountered such situations and their prior experience with 'read a list of values from standard input' didn't show them alternatives, so they didn't realize what they're up to... – Jonathan Leffler Oct 21 '12 at 06:13
  • 1
    You could have saved yourself a little grief by mentioning what `palloc()` is; it is reasonable to expect familiarity with C89 standard library, and mostly reasonable to assume C99 too. Move into the esoteric new portions of C2011 and you should mention that; move into POSIX or Windows APIs, and you should at least stipulate that. Move very far outside those and you should point to where people can find the information about what a function is and what it does. I didn't Google `palloc()` before, but there are a variety of versions; I hope they do more or less the same thing. – Jonathan Leffler Oct 21 '12 at 06:17