Implementing a simple ring buffer for float values - c++

I am trying to implement a very simple ring buffer, for holding a stream of audio samples in the form of float values.
I want to be able to take a snapshot of the audio input at any one time. I don't need to pop or delete any values, just keep a moving buffer of the last n samples.
I'd like to ask if there are any potential issues with this implementation for my purposes.
class RingBuffer
{
public:
RingBuffer (int bufferSize) : bufferSize (bufferSize), count (0), head (0)
{
buffer = static_cast<float *> (malloc(bufferSize * sizeof(float)));
readBuffer = static_cast<float *> (malloc(bufferSize * sizeof(float)));
}
~RingBuffer ()
{
if (buffer != nullptr) free(buffer);
buffer = nullptr;
if (readBuffer != nullptr) free(readBuffer);
readBuffer = nullptr;
}
void push (float value)
{
if (count < bufferSize && head == 0)
{
buffer[count++] = value;
}
else if (count == bufferSize)
{
// reset head to beginning if reached the end
if (head >= bufferSize)
{
head = 0;
buffer[head] = value;
}
else
{
buffer[head++] = value;
}
}
}
/**
* Return a snapshot of the buffer as a continous array
*/
const float* getSnapshot ()
{
// Set up read buffer as continuous stream
int writeIndex = 0;
for (int i = head; i < count; ++i)
{
readBuffer[writeIndex++] = buffer[i];
}
for (int i = 0; i < head; ++i)
{
readBuffer[writeIndex++] = buffer[i];
}
return readBuffer;
}
private:
int bufferSize, head, count;
float* buffer;
float* readBuffer;
};

Well, there are indeed several issues I can see. Sorry for the bad news :-/
Bugs
There is a bug here: buffer[head] = value;. You don't increment head, so the sample at this position will be lost (overwritten) when the next sample comes in.
In the constructor, you should initialize buffer and readBuffer to nullptr: if one of your mallocs failed, your destructor would try to free
Your 1st loop in getSnapshot is faulty: the end-point should be min(bufferSize,head+count) rather than count
Design issues
As pointed out by mathematician1975, you should allocate your arrays with new float[bufferSize], it's simpler and more readable than mallocs
You should hold each buffer using a std::unique_ptr, so that you would no longer need any destructor (and your code would be much safer)
As you are working on circular buffers, you should use modulo arithmetics, e.g. writeIndex = (writeIndex +1 ) % bufferSize. Your code will be much simpler that way, especially in getSnapshot (one loop instead of two)

Related

C++ malloc() memory corruption(fast)

I am fairly new to programming and am having memory issues with my program. Somewhere I am overusing memory, but can't find the source. I don't understand why it is giving me issues with malloc allocation as i don't dynamically allocate any variables. Thanks
//returns the index of the character in the string
int find(string line, int begin, int end, char character) {
for (int i = begin; i <= end; i++) {
if (line[i] == character) {
return i;
}
}
//return -1 if not found
return -1;
}
//Get the characters from levelorder that align with inorder
char* getCharacters(char inOrder[], char levelOrder[], int a, int b) {
char *newLevelOrder = new char[a];
int j = 0;
for (int i = 0; i <= b; i++)
if (find(inOrder, 0, a-1, levelOrder[i]) != -1)
newLevelOrder[j] = levelOrder[i], j++;
return newLevelOrder;
}
//creates a new Node given a character
Node* newNode(char character) {
Node *node = new Node;
node->character = character;
node->left = NULL;
node->right = NULL;
return node;
}
//creates the huffman tree from inorder and levelorder
Node* createInLevelTree(char inOrder[], char levelOrder[], int beginning, int end, int size) {
//if start index is out of range
if (beginning > end) {
return NULL;
}
//the head of the tree is the 1st item in level order's traversal
Node *head = newNode(levelOrder[0]);
//if there are no children we can't go farther down
if (beginning == end) {
return head;
}
//get the index of the node
int index = find(inOrder, beginning, end, head->character);
//get the subtree on the left
char *leftTree = getCharacters(inOrder, levelOrder, index, size);
//get the subtree on the right
char *rightTree = getCharacters(inOrder + index + 1, levelOrder, size-index-1, size);
//branch off to the left and right
head->left = createInLevelTree(inOrder, leftTree, beginning, index-1, size);
head->right = createInLevelTree(inOrder, rightTree, index+1, end, size);
//delete
delete [] leftTree;
delete [] rightTree;
return head;
}
Fixed with this line. Thanks Sam.
Char* new level order = new char [b]
Somewhere I am overusing memory, but can't find the source.
I'd suggest you at least replace your character arrays with std::vector<char> or std::string and put some size assertions in, or use the at member to see no over-indexing happens. Furthermore, using operator new more than likely is implemented in terms of malloc, and operator delete in terms of free. Therefore you are allocated dynamically.
Also, wiki for RAII. Try and employ RAII for dynamically allocated memory ... always. std::vector and std::string gives you this for free.
Also, consider the code below:
char* getCharacters(char inOrder[], char levelOrder[], int a, int b) {
char *newLevelOrder = new char[a];
int j = 0;
for (int i = 0; i <= b; i++)
if (find(inOrder, 0, a-1, levelOrder[i]) != -1)
newLevelOrder[j] = levelOrder[i], j++;
return newLevelOrder;
}
Reading this, I'm not sure of the quantity of b. There is no restriction imposed at the call sight. How do I know that the for loop won't invoke indefined behavior (by overindexing). Typically a correct for loop would use "a" here, as "a" was used to create the array... If you want to code like this, use asserts liberally, as you are making assumptions about the calling code (but just use a vector....).
char *newLevelOrder = new char[a];
int j = 0;
for (int i = 0; (i < a) && (i <= b); i++)
{
or
assert (b < a);
char *newLevelOrder = new char[a];
int j = 0;
for (int i = 0; (i <= b); i++)
{
I leave the task of replacing your arrays with vectors and string as an exercise for you, as well as liberally spraying asserts in for loops mentioned... That will likely solve your problems

Trying to push a value using a dynamic array in c++

I'm trying to write a function that pushes an item onto the end of my dynamically allocated array (not allowed to use vectors). Once it goes to the area to double the size of the list if the list was too small to store the next number, it all goes to hell and starts feeding me back random numbers from the computer. Can anyone see why it's not doubling like it's suuposed to?
int *contents_;
int *temp;
int size_ = 0;
int capacity_ = 1;
void pushBack(int item) /**appends the specified value to DynArray; if the contents array is full,
double the size of the contents array and then append the value **/
{
if (size_ == capacity_)
{
capacity_ = (2*capacity_);
temp = new int[capacity_];
for (int i = 0; i < size_; ++i)
{
temp[i] = contents_[i];
}
delete [] contents_;
contents_ = temp;
}
contents_[size_++] = item;
}
EDIT ** I forgot to mention. This is a function out of a class. This is in the header and in main :
main()
{
DynArray myArray;
myArray.pushBack(2);
myArray.pushBack(3);
myArray.printArray();
return 0;
}
If this is your initial setup:
int *contents_; // Junk
int size_ = 0;
int capacity_ = 1;
Then your code is most likely performing a memory access violation upon the first time it does:
if (size_ == capacity_)
{
// Not entering here, contents_ remains junk
}
contents_[size_++] = item;
As barak implied, the contents_ pointer needs to be initialized. If not, c++ will point it to something you probably don't want it to.

dynamic memory allocation with arrays in c++

I am trying to insert an int into an array that is in a class object, and I cannot figure out what I am doing wrong. The current state of my code never inserts the int into the array.
Basically what I am trying to do is when i call insert(int) it will check to to see if there is any room left in the array, and if there is it will add it, otherwise it would reallocate with 8 more spaces in the array.
here is some relevant class info
private:
unsigned Cap; // Current capacity of the set
unsigned Num; // Current count of items in the set
int * Pool; // Pointer to array holding the items
public:
// Return information about the set
//
bool is_empty() const { return Num == 0; }
unsigned size() const { return Num; }
unsigned capacity() const { return Cap; }
// Initialize the set to empty
//
Set()
{
Cap = Num = 0;
Pool = NULL;
}
here is the code i am working on
bool Set::insert(int X)
{
bool Flag = false;
if (Num == Cap)
{
//reallocate
const unsigned Inc = 8;
int * Temp = new int[Cap+Inc];
for (unsigned J=0;J<Num;J++)
{
Temp[J] = Pool[J];
}
delete [] Pool;
Pool = Temp;
Cap = Cap+Inc;
}
if(Num < Cap)
{
Pool[Num+1] = X;
Flag = true;
}
return Flag;
}
Your insert function never updates Num. Try Pool[Num++] = X; or something like that.
You probably want to increment the number of element but only after copying the new element in: the first element should have index 0. Basically, your insert() function should look something like this:
bool Set::insert(int X)
{
if (Num == Cap)
{
const unsigned Inc(std::max(8, 2 * Cap));
std::unique_ptr<int[]> Temp(new int[Cap+Inc]);
std::copy(Pool.get(), Pool.get() + Num, Temp.get());
Pool.swap(Temp);
Cap += Inc;
}
Pool[Num] = X;
++Num;
return true;
}
Of course, this assumes that Pool is reasonably declared as std::unique_ptr<int[]> (or something with similar functionality which is easy to write if necessary). The reason to use std::unique_ptr<int[]> rather than raw pointers is that they automatically clean up resources when they are destroyed. Copying a sequence of ints won't throw an exception but if int get's replaced by a std::string or a template parameters there is potential to throw exceptions.

C++ Lock free producer/consumer queue

I was looking at the sample code for a lock-free queue at:
http://drdobbs.com/high-performance-computing/210604448?pgno=2
(Also reference in many SO questions such as Is there a production ready lock-free queue or hash implementation in C++)
This looks like it should work for a single producer/consumer, although there are a number of typos in the code. I've updated the code to read as shown below, but it's crashing on me. Anybody have suggestions why?
In particular, should divider and last be declared as something like:
atomic<Node *> divider, last; // shared
I don't have a compiler supporting C++0x on this machine, so perhaps that's all I need...
// Implementation from http://drdobbs.com/high-performance-computing/210604448
// Note that the code in that article (10/26/11) is broken.
// The attempted fixed version is below.
template <typename T>
class LockFreeQueue {
private:
struct Node {
Node( T val ) : value(val), next(0) { }
T value;
Node* next;
};
Node *first, // for producer only
*divider, *last; // shared
public:
LockFreeQueue()
{
first = divider = last = new Node(T()); // add dummy separator
}
~LockFreeQueue()
{
while( first != 0 ) // release the list
{
Node* tmp = first;
first = tmp->next;
delete tmp;
}
}
void Produce( const T& t )
{
last->next = new Node(t); // add the new item
last = last->next; // publish it
while (first != divider) // trim unused nodes
{
Node* tmp = first;
first = first->next;
delete tmp;
}
}
bool Consume( T& result )
{
if (divider != last) // if queue is nonempty
{
result = divider->next->value; // C: copy it back
divider = divider->next; // D: publish that we took it
return true; // and report success
}
return false; // else report empty
}
};
I wrote the following code to test this. Main (not shown) just calls TestQ().
#include "LockFreeQueue.h"
const int numThreads = 1;
std::vector<LockFreeQueue<int> > q(numThreads);
void *Solver(void *whichID)
{
int id = (long)whichID;
printf("Thread %d initialized\n", id);
int result = 0;
do {
if (q[id].Consume(result))
{
int y = 0;
for (int x = 0; x < result; x++)
{ y++; }
y = 0;
}
} while (result != -1);
return 0;
}
void TestQ()
{
std::vector<pthread_t> threads;
for (int x = 0; x < numThreads; x++)
{
pthread_t thread;
pthread_create(&thread, NULL, Solver, (void *)x);
threads.push_back(thread);
}
for (int y = 0; y < 1000000; y++)
{
for (unsigned int x = 0; x < threads.size(); x++)
{
q[x].Produce(y);
}
}
for (unsigned int x = 0; x < threads.size(); x++)
{
q[x].Produce(-1);
}
for (unsigned int x = 0; x < threads.size(); x++)
pthread_join(threads[x], 0);
}
Update: It ends up that the crash is being caused by the queue declaration:
std::vector<LockFreeQueue<int> > q(numThreads);
When I change this to be a simple array, it runs fine. (I implemented a version with locks and it was crashing too.) I see that the destructor is being called immediate after the constructor, resulting in doubly-freed memory. But, does anyone know WHY the destructor would be called immediately with a std::vector?
You'll need to make several of the pointers std::atomic, as you note, and you'll need to use compare_exchange_weak in a loop to update them atomically. Otherwise, multiple consumers might consume the same node and multiple producers might corrupt the list.
It's critically important that these writes (just one example from your code) occur in order:
last->next = new Node(t); // add the new item
last = last->next; // publish it
That's not guaranteed by C++ -- the optimizer can rearrange things however it likes, as long as the current thread always acts as-if the program ran exactly the way you wrote it. And then the CPU cache can come along and reorder things further.
You need memory fences. Making the pointers use the atomic type should have that effect.
This could be totally off the mark, but I can't help but wonder whether you're having some sort of static initialization related issue... For laughs, try declaring q as a pointer to a vector of lock-free queues and allocating it on the heap in main().

Huffman Decoding Sub-Table

I've been trying to implement a huffman decoder, and my initial attempt suffered from low performance due to a sub-optimal choice of decoding algorithm.
I thought I try to implement huffman decoding using table-lookups. However, I go a bit stuck on generating the subtables and was hoping someone could point me in the right direction.
struct node
{
node* children; // 0 right, 1 left
uint8_t value;
uint8_t is_leaf;
};
struct entry
{
uint8_t next_table_index;
std::vector<uint8_t> values;
entry() : next_table_index(0){}
};
void build_tables(node* nodes, std::vector<std::array<entry, 256>>& tables, int table_index);
void unpack_tree(void* data, node* nodes);
std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> decode_huff(void* input)
{
// Initial setup
CACHE_ALIGN node nodes[512] = {};
auto data = reinterpret_cast<unsigned long*>(input);
size_t table_size = *(data++); // Size is first 32 bits.
size_t result_size = *(data++); // Data size is second 32 bits.
unpack_tree(data, nodes);
auto huffman_data = reinterpret_cast<long*>(input) + (table_size+32)/32;
size_t data_size = *(huffman_data++); // Size is first 32 bits.
auto huffman_data2 = reinterpret_cast<char*>(huffman_data);
// Build tables
std::vector<std::array<entry, 256>> tables(1);
build_tables(nodes, tables, 0);
// Decode
uint8_t current_table_index = 0;
std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> result;
while(result.size() < result_size)
{
auto& table = tables[current_table_index];
uint8_t key = *(huffman_data2++);
auto& values = table[key].values;
result.insert(result.end(), values.begin(), values.end());
current_table_index = table[key].next_table_index;
}
result.resize(result_size);
return result;
}
void build_tables(node* nodes, std::vector<std::array<entry, 256>>& tables, int table_index)
{
for(int n = 0; n < 256; ++n)
{
auto current = nodes;
for(int i = 0; i < 8; ++i)
{
current = current->children + ((n >> i) & 1);
if(current->is_leaf)
tables[table_index][n].values.push_back(current->value);
}
if(!current->is_leaf)
{
if(current->value == 0)
{
current->value = tables.size();
tables.push_back(std::array<entry, 256>());
build_tables(current, tables, current->value);
}
tables[table_index][n].next_table_index = current->value;
}
}
}
void unpack_tree(void* data, node* nodes)
{
node* nodes_end = nodes+1;
bit_reader table_reader(data);
unsigned char n_bits = ((table_reader.next_bit() << 2) | (table_reader.next_bit() << 1) | (table_reader.next_bit() << 0)) & 0x7; // First 3 bits are n_bits-1.
// Unpack huffman-tree
std::stack<node*> stack;
stack.push(&nodes[0]); // "nodes" is root
while(!stack.empty())
{
node* ptr = stack.top();
stack.pop();
if(table_reader.next_bit())
{
ptr->is_leaf = 1;
ptr->children = nodes[0].children;
for(int n = n_bits; n >= 0; --n)
ptr->value |= table_reader.next_bit() << n;
}
else
{
ptr->children = nodes_end;
nodes_end += 2;
stack.push(ptr->children+0);
stack.push(ptr->children+1);
}
}
}
First off, avoid all those vectors. You can have pointers into a single preallocated buffer, but you don't want the scenario where vector allocates these tiny, tiny buffers all over memory, and your cache footprint goes through the roof.
Note also that the number of non-leaf states might be much less than 256. Indeed, it might be as low as 128. By assigning them low state IDs, we can avoid generating table entries for the entire set of state nodes (which may be as high as 511 nodes in total). After all, after consuming input, we'll never end up on a leaf node; if we do, we generate output, then head back to the root.
The first thing we should do, then, is reassign those states that correspond to internal nodes (ie, ones with pointers out to non-leaves) to low state numbers. You can use this to also reduce memory consumption for your state transition table.
Once we've assigned these low state numbers, we can go through each possible non-leaf state, and each possible input byte (ie, a doubly-nested for loop). Traverse the tree as you would for a bit-based decoding algorithm, and record the set of output bytes, the final node ID you end up on (which must not be a leaf!), and whether you hit an end-of-stream mark.