<commit_before>#include "common.h"
#include <cassert>
#include <cmath>
#include <cstring>

#include "Memory.h"

#define NUM_BUFFER_BITS 16
#define MAX_NUM_BUFFERS ((size_t)1 << NUM_BUFFER_BITS)
#define NUM_ADDRESS_BITS ((sizeof(size_t)<<3) - NUM_BUFFER_BITS)
#define MAX_BUFFER_SIZE ((size_t)1 << NUM_ADDRESS_BITS)

#define EXTRACT_BUFFER(address) \
  (address >> NUM_ADDRESS_BITS)
#define EXTRACT_OFFSET(address) \
  (address ^ (EXTRACT_BUFFER(address) << NUM_ADDRESS_BITS))

using namespace spirsim;
using namespace std;

Memory::Memory()
{
  clear();
}

Memory::~Memory()
{
  clear();
}

size_t Memory::allocateBuffer(size_t size)
{
  // Check requested size doesn't exceed maximum
  if (size > MAX_BUFFER_SIZE)
  {
    return NULL;
  }

  // Find first unallocated buffer slot
  int b = getNextBuffer();
  if (b < 0 || b >= MAX_NUM_BUFFERS)
  {
    return NULL;
  }

  // Create buffer
  Buffer buffer = {
    false,
    size,
    new unsigned char[size]
  };

  // Initialize contents to 0
  // TODO: Solution to catch use of uninitialised data
  memset(buffer.data, 0, size);

  m_memory[b] = buffer;
  m_totalAllocated += size;

  return ((size_t)b) << NUM_ADDRESS_BITS;
}

void Memory::clear()
{
  map<int,Buffer>::iterator itr;
  for (itr = m_memory.begin(); itr != m_memory.end(); itr++)
  {
    if (!itr->second.hostPtr)
    {
      delete[] itr->second.data;
    }
  }
  m_memory.clear();
  m_freeBuffers = queue<int>();
  m_totalAllocated = 0;

  // Reserve first buffer as a makeshift 'NULL'
  m_memory[0].data = new unsigned char[0];

}

Memory* Memory::clone() const
{
  Memory *mem = new Memory();

  // Clone buffers
  map<int,Buffer>::const_iterator itr;
  for (itr = m_memory.begin(); itr != m_memory.end(); itr++)
  {
    Buffer src = itr->second;
    Buffer dest = {
      src.hostPtr,
      src.size,
      src.hostPtr ? src.data : new unsigned char[src.size]
    };
    memcpy(dest.data, src.data, src.size);
    mem->m_memory[itr->first] = dest;
  }

  // Clone state
  mem->m_freeBuffers = m_freeBuffers;
  mem->m_totalAllocated = m_totalAllocated;

  return mem;
}<commit_msg>Fixed leak in Memory class for its NULL buffer.<commit_after>#include "common.h"
#include <cassert>
#include <cmath>
#include <cstring>

#include "Memory.h"

#define NUM_BUFFER_BITS 16
#define MAX_NUM_BUFFERS ((size_t)1 << NUM_BUFFER_BITS)
#define NUM_ADDRESS_BITS ((sizeof(size_t)<<3) - NUM_BUFFER_BITS)
#define MAX_BUFFER_SIZE ((size_t)1 << NUM_ADDRESS_BITS)

#define EXTRACT_BUFFER(address) \
  (address >> NUM_ADDRESS_BITS)
#define EXTRACT_OFFSET(address) \
  (address ^ (EXTRACT_BUFFER(address) << NUM_ADDRESS_BITS))

using namespace spirsim;
using namespace std;

Memory::Memory()
{
  clear();
}

Memory::~Memory()
{
  clear();

  delete[] m_memory[0].data;
}

size_t Memory::allocateBuffer(size_t size)
{
  // Check requested size doesn't exceed maximum
  if (size > MAX_BUFFER_SIZE)
  {
    return NULL;
  }

  // Find first unallocated buffer slot
  int b = getNextBuffer();
  if (b < 0 || b >= MAX_NUM_BUFFERS)
  {
    return NULL;
  }

  // Create buffer
  Buffer buffer = {
    false,
    size,
    new unsigned char[size]
  };

  // Initialize contents to 0
  // TODO: Solution to catch use of uninitialised data
  memset(buffer.data, 0, size);

  m_memory[b] = buffer;
  m_totalAllocated += size;

  return ((size_t)b) << NUM_ADDRESS_BITS;
}

void Memory::clear()
{
  map<int,Buffer>::iterator itr;
  for (itr = m_memory.begin(); itr != m_memory.end(); itr++)
  {
    if (!itr->second.hostPtr)
    {
      delete[] itr->second.data;
    }
  }
  m_memory.clear();
  m_freeBuffers = queue<int>();
  m_totalAllocated = 0;

  // Reserve first buffer as a makeshift 'NULL'
  m_memory[0].data = new unsigned char[0];
}

Memory* Memory::clone() const
{
  Memory *mem = new Memory();

  // Clone buffers
  map<int,Buffer>::const_iterator itr;
  for (itr = m_memory.begin(); itr != m_memory.end(); itr++)
  {
    Buffer src = itr->second;
    Buffer dest = {
      src.hostPtr,
      src.size,
      src.hostPtr ? src.data : new unsigned char[src.size]
    };
    memcpy(dest.data, src.data, src.size);
    mem->m_memory[itr->first] = dest;
  }

  // Clone state
  mem->m_freeBuffers = m_freeBuffers;
  mem->m_totalAllocated = m_totalAllocated;

  return mem;
}
{'fraction_non_alphanumeric': 0.14312485359568985, 'fraction_numerical': 0.0053876786132583745, 'mean_word_length': 3.5570971184631803, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6575857', 'n_tokens_mistral': 1595, 'n_tokens_neox': 1550, 'n_words': 362}