LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices

Reply
 
Search this Thread
Old 11-08-2011, 01:56 PM   #1
mrjextreme6
LQ Newbie
 
Registered: Nov 2011
Posts: 3

Rep: Reputation: Disabled
How to fix this: glibc detected: double free or corruption


I am trying to simulate a memory management system using first-fit algorithm. It mallocs a chunk of memory space and creates a threadpool where each thread allocates pieces of the memory and then frees it. Clearly my algorithm needs work because they all keep writing to the same base address (nil) but I doubt that's causing the issue. When I close the program and attempt to free the memory, I get the following output:


:~/Documents/OS_3$ ./mem_manager 5
Thread 0 allocated to base (nil) with size 1383
Free Space Left: 2713

Here!
Thread 1 allocated to base (nil) with size 2153
Free Space Left: 560

Thread 2 could not allocate size 3153
Thread 3 could not allocate size 1098
Thread 4 could not allocate size 3881
Thread 4 could not allocate size 2234
Here!
Thread 3 allocated to base (nil) with size 498
Free Space Left: 62

^C

*** glibc detected *** ./mem_manager: double free or corruption (!prev): 0x0000000001362010 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x78a96)[0x7f3df63aea96]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x6c)[0x7f3df63b2d7c]
./mem_manager[0x400e7c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f3df635730d]
./mem_manager[0x4008f9]
======= Memory map: ========
.....(etc.)



Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h> // Object files must be compiled with gcc's -lpthread flag
#include <unistd.h>
#include <signal.h>

#define MAX_SIZE 4096 // Max memory size of system
#define MAX_WAIT_TIME 10 // Maximum sleep time
#define INVALID -1
#define ERROR INVALID

typedef struct page { // Page data type
  unsigned char *base;
  int size;
  int owner;
} Page;

typedef struct pageTable { // Page table data type
  Page *table;
  int number;
  int owner;
} PageTable;

typedef struct memoryBlock { // Memory block data type
  unsigned char *memBlock; // Pointer to allocated memory block
  int freeSpace; // Number of unallocated bytes within memory block
} MemoryBlock;

// Global data
MemoryBlock memory; // Memory block
PageTable pages; // Page table
int numThreads; // Number of threads
unsigned char **base_ptrs; // Array of base pointers
int running  = 1; // Signal handler variable

void signalHandler(int sig);
unsigned char *memory_malloc(MemoryBlock *p_memory, PageTable *p_pages, int size);
void memory_free(MemoryBlock *p_memory, PageTable *p_pages, unsigned char *base, unsigned char **base_ptrs);
unsigned char *first_fit(MemoryBlock *p_memory, PageTable *p_pages, int size);
void *thread(void *ptr);

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // Initialize mutex

int main(int argc, char *argv[])
{
  int i;

  signal(SIGINT, signalHandler); // Initialize signal handler

  if (argc < 2) // Is input missing?
    {
      fprintf(stderr, "ERROR: Number of threads unspecified\n");
      exit(1);
    }

  numThreads = atoi(argv[1]);

  if (numThreads < 1) // Is number of threads greater than zero?
    {
      fprintf(stderr, "ERROR: Number of threads less than 1\n");
      exit(1);
    }

  if ((memory.memBlock = (unsigned char*) malloc(sizeof(unsigned char) * MAX_SIZE)) == NULL)
    {
      fprintf(stderr, "ERROR: Not enough memory in system\n");
      exit(1);
    }

  memory.freeSpace = MAX_SIZE;

  // Allocate page table
  if ((pages.table = (Page *) malloc(sizeof(Page) * numThreads)) == NULL)
    {
      fprintf(stderr, "ERROR: Not enough memory for page table\n");
      free(memory.memBlock);
      memory.memBlock = NULL;
      memory.freeSpace = 0x00;
      exit(1);
    }

  // Initialize page table
  for (i = 0; i < numThreads; i++)
    {
      pages.table[i].base = NULL;
      pages.table[i].size = 0x00;
      pages.table[i].owner = INVALID;
    }

  pages.number = numThreads;

  // Allocate base pointer array
  if ((base_ptrs = (unsigned char **) malloc(sizeof(unsigned char *) * numThreads)) == NULL)
    {
      fprintf(stderr, "ERROR: Not enough memory for base pointer array\n");
       free(memory.memBlock);
       free(pages.table);
       memory.memBlock = NULL;
       memory.freeSpace = 0x00;
       pages.table = NULL;
       pages.number = 0x00;
       exit(1);
    }

  // Initialize base pointer array
  for (i = 0; i < numThreads; i++)
    {
      base_ptrs[i] = NULL;
    }

  pthread_t threadPool[numThreads]; // Thread pool
  int threadIDs[numThreads]; // Thread IDs

  // Create threads
  for (i = 0; i < numThreads; i++)
    {
      threadIDs[i] = i;
      if (pthread_create(&threadPool[i], NULL, thread, (void *)&threadIDs[i]))
	{
	  fprintf(stderr, "ERROR: thread %d creation failure\n", i);
	  free(memory.memBlock);
	  free(pages.table);
	  free(base_ptrs);
	  memory.memBlock = NULL;
	  memory.freeSpace = 0x00;
	  pages.table = NULL;
	  pages.number = 0x00;
	  exit(1);
	}
    }

  // Join threads
  for (i = 0; i < numThreads; i++)
    {
      pthread_join(threadPool[i], NULL);
    }

  // Free memory
  free(memory.memBlock);
  free(pages.table);
  free(base_ptrs);
  memory.memBlock = NULL;
  memory.freeSpace = 0x00;
  pages.table = NULL;
  pages.number = 0x00;

  printf("\n\nAll threads returned successfully!\n\n");

  return 0;
}

// Signal Handler
void signalHandler(int sig)
{
  running = 0;
  return;
}

// Allocates chunk of memory to a thread
unsigned char *memory_malloc(MemoryBlock *p_memory, PageTable *p_pages, int size)
{
  if (p_memory->freeSpace < size) // Is there enough total free memory?
    {
      return NULL;
    }

  else
    {
      return first_fit(p_memory, p_pages, size);
    }
}

void memory_free(MemoryBlock *p_memory, PageTable *p_pages, unsigned char *base, unsigned char **base_ptrs)
{
  int i, j, k;

  for (i = 0; i < p_pages->number; i++)
    {
      if ((*p_pages).table[i].base == base) // If page match, remove from page table and free space in memory block
	{
	  p_memory->freeSpace += (*p_pages).table[i].size;
	  base_ptrs[(*p_pages).table[i].owner] = NULL;
	  (*p_pages).table[i].size = 0x00;
	  (*p_pages).table[i].owner = INVALID;
	  break;
	}
    }

  k = i;

  // Group all freed blocks
  for (j = i; j < (p_pages->number - 1); j++)
    {
      if ((*p_pages).table[j + 1].base)
	{
	  (*p_pages).table[k].size = (*p_pages).table[j + 1].size;
	  (*p_pages).table[k].owner = (*p_pages).table[j + 1].owner;
	  base_ptrs[(*p_pages).table[k].owner] = (*p_pages).table[k].base;
	  (*p_pages).table[k + 1].base = (*p_pages).table[k].base + (*p_pages).table[k].size;
	  k++;
	}
    }

  (*p_pages).table[k].base = NULL;
  (*p_pages).table[k].size = 0x00;
  (*p_pages).table[k].owner = INVALID;

  return;
}

unsigned char *first_fit(MemoryBlock *p_memory, PageTable *p_pages, int size)
{
  int i,  j;

  for (i = 0; i < (p_pages->number - 1); i++)
    {
      if (((*p_pages).table[i].base != NULL) && ((*p_pages).table[i + 1].base == NULL))
	{
	  printf("Here!\n");
	  for (j = (i + 1); j < p_pages->number; j++)
	    {
	      if ((*p_pages).table[j].base)
		{
		  if (((*p_pages).table[j].base - ((*p_pages).table[i].base + (*p_pages).table[i].size)) >= size)
		    {
		      (*p_pages).table[i + 1].base = (*p_pages).table[i].base + (*p_pages).table[i].size;
		      (*p_pages).table[i + 1].size = size;
		      p_memory->freeSpace -= size;
		      return (*p_pages).table[i + 1].base;
		    }
		  else
		    {
		      j = p_pages->number + 1;
		    }
		}
	    }
	  if (j == p_pages->number)
	    {
	      (*p_pages).table[i + 1].base = (*p_pages).table[i].base + (*p_pages).table[i].size;
	      (*p_pages).table[i + 1].size = size;
	      p_memory->freeSpace -= size;
	      return (*p_pages).table[i + 1].base;
	    }
	}
    }
  (*p_pages).table[0].base = (*p_memory).memBlock;
  (*p_pages).table[0].size = size;
  p_memory->freeSpace -= size;
  return (*p_pages).table[0].base;
}

void *thread(void *ptr)
{
  int threadID = *((int *)(ptr));
  int allocated = 0;
  int random_size; // random allocation size
  int random_time; // random sleep time
  void *base_address;

  while (running)
    {
      pthread_mutex_lock(&mutex); // Grab the mutex
      random_size = (int)(((unsigned int)rand()) % MAX_SIZE); // Generate random number of bytes to allocate no greater than MAX_SIZE
      base_address = (void*)base_ptrs[threadID];
      random_time = rand() % MAX_WAIT_TIME;

      if (allocated)
	{
	  memory_free(&memory, &pages, base_ptrs[threadID], base_ptrs);
	  allocated = 0;
	}
      else
	{
	  if ((base_ptrs[threadID] = memory_malloc(&memory, &pages, random_size)))
	    {
	      printf("Thread %d allocated to base %p with size %d\n", threadID, base_address, random_size);
	      printf("Free Space Left: %d\n\n", memory.freeSpace);
	      allocated = 1;
	    }
	  else
	    {
	      printf("Thread %d could not allocate size %d\n", threadID, random_size);
	      allocated = 0;
	    }
	}
      pthread_mutex_unlock(&mutex);

      sleep(random_time);
    }

  return (void *)NULL;
}
I suspect this has to do with my attempt to free my **base_ptrs variable.

Does anyone have any suggestions please?

Thank you!

Last edited by mrjextreme6; 11-09-2011 at 09:54 AM.
 
Old 11-09-2011, 06:54 AM   #2
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,051

Rep: Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100
Please use CODE tags around your code so you can preserve the indentation.

I'll look at your code later anyway to see if I can easily spot the bug. But others might choose not to look at it because you didn't use CODE tags.
 
Old 11-09-2011, 10:01 AM   #3
mrjextreme6
LQ Newbie
 
Registered: Nov 2011
Posts: 3

Original Poster
Rep: Reputation: Disabled
Thank you for the advice. I've revised my thread post.

I figured out the algorithm issue but I still get the glibc error when I attempt to free my allocated memory.
 
Old 11-09-2011, 03:58 PM   #4
mrjextreme6
LQ Newbie
 
Registered: Nov 2011
Posts: 3

Original Poster
Rep: Reputation: Disabled
Nevermind, I figured out the problem.

Turns out I forgot set my pages.table[].owner values which I used as indexes for memory allocation. Since I didn't set them, the program started accessing pointers outside my array.

Thanks though!
 
  


Reply

Tags
corruption, double, free, glibc, malloc


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
*** glibc detected *** double free or corruption vvenugop Linux - General 0 02-19-2008 09:11 AM
glibc detected *** double free or corruption (!prev): krishna_162005 Linux - Server 2 06-29-2007 08:26 AM
*** glibc detected *** double free or corruption (!prev): krishna_162005 Linux - General 1 06-27-2007 02:43 AM
*** glibc detected *** double free or corruption - ERROR bandwidthjunkie Programming 2 03-19-2007 09:36 AM
*** glibc detected *** double free or corruption (C++) urzumph Programming 25 01-07-2006 04:03 PM


All times are GMT -5. The time now is 12:20 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration