To immprove performance i was trying to implement a aligned_malloc() function to allocate new memory with an aligned address , i know the "new" operator returns always an aligned address but i want to write my own function for better understanding , this is my try :
#include <iostream>
#include <stdlib.h>
/*
in purpose let's make our struct not aligned
*/
struct s{
char foo[3];
};
s * array = NULL;
template <class t>
t* aligned_malloc(size_t array_size)
{
t* array = NULL;
char * ptr = (char*) malloc((array_size+1)*sizeof(t)); // array_size+1 to not get out of memory when incrementing pointer
while((((uintptr_t)ptr)%sizeof(t)) != 0 )
++ptr;
return ((t*)ptr);
}
int main()
{
struct s * array = aligned_malloc<s>(10);
/*
let's test for crashs
*/
for (int c=0;c<10;c++)
{
array[c].foo[3] = 'f';
}
std::cout<<(((int)array)%sizeof(s))<<std::endl; // allways show '0' ,like the operator "new"
system("pause");
}
An other way to do it , is by creating a memory manager that allocates a big memory block and returns the aligned address for each request .
Note : im not assuming that this is the correct way to do it , i wrote this for learning purposes , not assuming & not claiming .
Related
Hello stackoverflow
so my question is: I want to make a function to generate the array of structures but i get an error whenever i finish inserting the values what is the problem?
like so
struct INFO
{
char name[20]; // creating the strucure
int age;
};
void generateArr(INFO *p); // a function to generate the array
void readArr(INFO *p); // a function to read the array
int main()
{
INFO *ptr =new INFO; // a pointer that points to the structure
generateArr(ptr); // calling the functions
readArr(ptr);
delete[]ptr; // deallocating memory
}
void generateArr(INFO *p)
{
p = new INFO [3]; // generating three INFO structures
}
void readArr(INFO *p)
{
for (int i = 0; i < 3; i++)
{
cin >> p[i].name>> p[i].age; // inputting the elements
cout << endl;
}
}
I tried to make the code as clear as possible, ask me if anything is ambiguous.
This function :
void generateArr(INFO *p)
{
p = new INFO [3]; // generating three INFO structures
}
is not working as you expect it does. It assigns allocated memory to local 'p` parameter, which is not returned to a main. To fix it change p to reference:
void generateArr(INFO *&p)
[edit]
but since you already assigned ptr in main with INFO *ptr =new INFO;, you will get a memory leak this way. So you should remove that line.
In generateArr(INFO *p), you allocate an array which address is stored in local variable p; on return from the function, any local variable (such as p) is lost, as long as address of the allocated array.
You should get rid of function generateArr(INFO *p), which is useless, and allocate your array into main(), this way :
int main()
{
INFO *ptr =new INFO[3];
readArr(ptr);
delete[]ptr; // deallocating memory
}
Rewrite the functions at least the following way
INFO * generateArr( size_t n )
{
return new INFO [n]; // generating three INFO structures
}
void readArr(INFO *p, size_t n )
{
for (int i = 0; i < n; i++)
{
cin >> p[i].name>> p[i].age; // inputting the elements
cout << endl;
}
}
and in main call them like
const size_t N = 3;
INFO *ptr = generateArr( N ); // a pointer that points to the structure
readArr( ptr, N );
delete []ptr; // deallocating memory
As for your code then in this statement
INFO *ptr =new INFO; // a pointer that points to the structure
there is allocated only one object of the structure type however it is deleted using operator delete [] instead of the operator delete.
delete[]ptr; // deallocating memory
And inside this function
void generateArr(INFO *p)
{
p = new INFO [3]; // generating three INFO structures
}
there is a memory leak because variable p is a local variable of the function that was initialized by the value of the function's argument and that will be destroyed after exiting the function. As result the address of the dynamically allocated memory will be lost.
I currently have a c++ class as follows:
template<class T>
class MyQueue {
T** m_pBuffer;
unsigned int m_uSize;
unsigned int m_uPendingCount;
unsigned int m_uAvailableIdx;
unsigned int m_uPendingndex;
public:
MyQueue(): m_pBuffer(NULL), m_uSize(0), m_uPendingCount(0), m_uAvailableIdx(0),
m_uPendingndex(0)
{
}
~MyQueue()
{
delete[] m_pBuffer;
}
bool Initialize(T *pItems, unsigned int uSize)
{
m_uSize = uSize;
m_uPendingCount = 0;
m_uAvailableIdx = 0;
m_uPendingndex = 0;
m_pBuffer = new T *[m_uSize];
for (unsigned int i = 0; i < m_uSize; i++)
{
m_pBuffer[i] = &pItems[i];
}
return true;
}
};
So, I have this pointer to arrays m_pBuffer object and I was wondering if it is possible to replace this way of doing things with the c++ smart pointer perhaps? I know I can do things like:
std::unique_ptr<T> buffer(new T[size]);
Is using a vector of smart pointers the way to go? Is this recommended and safe?
[EDIT]
Based on the answers and the comments, I have tried to make a thread-safe buffer array. Here it is. Please comment.
#ifndef __BUFFER_ARRAY_H__
#define __BUFFER_ARRAY_H__
#include <memory>
#include <vector>
#include <mutex>
#include <thread>
#include "macros.h"
template<class T>
class BufferArray
{
public:
class BufferArray()
:num_pending_items(0), pending_index(0), available_index(0)
{}
// This method is not thread-safe.
// Add an item to our buffer list
void add(T * buffer)
{
buffer_array.push_back(std::unique_ptr<T>(buffer));
}
// Returns a naked pointer to an available buffer. Should not be
// deleted by the caller.
T * get_available()
{
std::lock_guard<std::mutex> lock(buffer_array_mutex);
if (num_pending_items == buffer_array.size()) {
return NULL;
}
T * buffer = buffer_array[available_index].get();
// Update the indexes.
available_index = (available_index + 1) % buffer_array.size();
num_pending_items += 1;
return buffer;
}
T * get_pending()
{
std::lock_guard<std::mutex> lock(buffer_array_mutex);
if (num_pending_items == 0) {
return NULL;
}
T * buffer = buffer_array[pending_index].get();
pending_index = (pending_index + 1) % buffer_array.size();
num_pending_items -= 1;
}
private:
std::vector<std::unique_ptr<T> > buffer_array;
std::mutex buffer_array_mutex;
unsigned int num_pending_items;
unsigned int pending_index;
unsigned int available_index;
// No copy semantics
BufferArray(const BufferArray &) = delete;
void operator=(const BufferArray &) = delete;
};
#endif
Vector of smart pointers is good idea. It is safe enough inside your class - automatic memory deallocation is provided.
It is not thread-safe though, and it's not safe in regard of handling external memory given to you by simple pointers.
Note that you current implementation does not delete pItems memory in destructor, so if after refactoring you mimic this class, you should not use vector of smart pointers as they will delete memory referenced by their pointers.
On the other side you cannot garantee that noone outside will not deallocate memory for pItems supplied to your Initialize. IF you want to use vector of smart pointers, you should formulate contract for this function that clearly states that your class claims this memory etc. - and then you should rework outside code that calls your class to fit into new contract.
If you don't want to change memory handling, vector of simple pointers is the way to go. Nevertheless, this piece of code is so simple, that there is no real benefit of vector.
Note that overhead here is creation of smart pointer class for each buffer and creation of vector class. Reallocation of vector can take up more memory and happens without your direct control.
The code has two issues:
1) Violation of the rule of zero/three/five:
To fix that you do not need a smart pointer here. To represent a dynamic array with variable size use a std:vector<T*>. That allows you to drop m_pBuffer, m_uSize and the destructor, too.
2) Taking the addresses of elements of a possible local array
In Initialize you take the addresses of the elements of the array pItems passed as argument to the function. Hence the queue does not take ownership of the elements. It seems the queue is a utility class, which should not be copyable at all:
template<class T>
class MyQueue
{
std::vector<T*> m_buffer;
unsigned int m_uPendingCount;
unsigned int m_uAvailableIdx;
unsigned int m_uPendingndex;
public:
MyQueue(T *pItems, unsigned int uSize)
: m_buffer(uSize, nullptr), m_uPendingCount(0), m_uAvailableIdx(0), m_uPendingndex(0)
{
for (unsigned int i = 0; i < uSize; i++)
{
m_buffer[i] = &pItems[i];
}
}
private:
MyQueue(const MyQueue&); // no copy (C++11 use: = delete)
MyQueue& operator = (const MyQueue&); // no copy (C++11 use: = delete)
};
Note:
The red herring is the local array.
You may consider a smart pointer for that, but that is another question.
I am given a task to simulate a linked list structure, but using an array of Nodes rather than an actual linked list. When I call my append function, I want to check to see if my existing array is full, and if it is, I want to double the array size, and append my Node to the end of the "list" (array).
I am having trouble doubling my array size.
To give you context, here is my some of my .h file:
...
const int NULL_INDEX = -1;
struct Node {
char info;
int next;
};
class LList1 {
private:
Node free [4];
// When more memory is called for, the array will double in size
// returns true if reallocation of memory was successful
bool doubleSize();
.
.
.
}
and here is the part of my .cpp file that tries to double the array size:
bool LList1::doubleSize() {
Node* newArray = new Node[this->length()*2];
memcpy(newArray, free, this->length()*2);
free = newArray;
return true;
}
I also tried using realloc and other functions. I keep having the same problem.
The line
"free = newArray"
keeps giving me this error in XCode: "Array type 'Node[4]' is not assignable"
Please give me some insight into a better way to do this. All solutions online seem to work fine for arrays of ints, but not for my array of Nodes.
Much appreciated.
A couple of things are incorrect in your code:
Your free property is a static array. In your case you need a dynamic one, with proper constructor.
The memcpy command takes the size in bytes, hence you need to multiply by sizeof(Node).
Perhaps it was intended, but the doubleSize() method was private.
Here is a corrected version of the code that compiles and runs:
...
const int NULL_INDEX = -1;
struct Node {
char info;
int next;
};
class LList1 {
public:
LList1();
~LList1();
int getLength();
bool doubleSize();
private:
int length;
Node* free;
// When more memory is called for, the array will double in size
// returns true if reallocation of memory was successful
};
int LList1::getLength() {
return this->length;
}
LList1::LList1() {
this->free = new Node[4]; // Default size
this->length = 4;
}
LList1::~LList1() {
delete []this->free;
}
bool LList1::doubleSize() {
Node* newArray = new Node[this->length*2];
memcpy(newArray, free, this->length * sizeof(Node));
free = newArray;
this->length *= 2;
return true;
}
int main(int, char **) {
LList1 l;
std::cout << "Original length: " << l.getLength() << std::endl;
l.doubleSize();
std::cout << "After doubling length: " << l.getLength() << std::endl;
return 0;
}
You are getting confused between arrays and pointers. Your variable free is a constant pointer which cannot be reassigned. You need to change Node free [4] to Node *free if you want to modify its value.
C/C++ int[] vs int* (pointers vs. array notation). What is the difference?
I have created a vector of class objects. The following program crashes with
"Pointer being freed was not allocated".
I have deep copied as well. I don't see where the double delete is happening. What am I missing ?.
#include <iostream>
#include <vector>
using namespace std;
enum MessageType { HEADER, DATA, CLOSE};
typedef class bufferElement{
public:
char *buffer ; //The actual data
int64_t length; //length of the data
MessageType messagetype;
/**
* Copy constructor for the structure
*/
bufferElement(const struct bufferElement &toCopy)
{
std::cout << "Copying the buffer vector - Copy Constructor for buffer" << std::endl;
buffer = new char[toCopy.length];
memcpy(buffer,toCopy.buffer,toCopy.length);
length = toCopy.length;
messagetype = toCopy.messagetype;
}
bufferElement()
{
buffer = NULL;
length =0;
messagetype = HEADER;
}
/**
* Initialises the vector element
* #param messagetype
* what type of message is the particular element.
* #param element
* The buffer element
* #param length_t
* The length/size of the buffer element
*/
bufferElement(char *element, int64_t length_t, MessageType messagetype_t) //constructor
{
std::cout << "The buffer element is Initialized" << std::endl;
buffer = new char[length_t];
messagetype = messagetype_t;
length = length_t;
memcpy(buffer, element, length_t);
}
~bufferElement()
{
std::cout << "Freeing the buffer in the vector - Destructor" << std::endl;
delete buffer;
buffer = NULL;
}
} messageHolder;
int main()
{
vector<messageHolder> v;
for(int64_t i=0; i< 1000000000000000000; i++)
{
int size = rand()%10000+5;
char *test = new char[size];
messageHolder m(test, size, HEADER );
v.push_back(m);
if(rand()%3)
{
v.erase(v.begin());
}
}
return 0;
}
I haven't looked at your code in detail, but if you think you need a copy constructor, you also need an assignment operator. And, why, why, why write this stuff anyway? Why not use std::string? Do you feel the need to write your own floating point types? No, I didn't think so.
Use delete[] instead of delete, since you are freeing an array.
By the way, in main(), you should also invoke delete[] test;, otherwise, you'll get a memory leak.
In general I would avoid using objects with pointers as members (like buffer in your bufferElement) as types in vector (or any other stl container for that matter) without a copy constructor AND an assignment operator. If the destructor frees that pointer it's a recipe for destruction. You should eighter
a) provide both the copy ctr and the assignment op
OR
b) don't use pointers (use smart pointers like boost::scoped_ptr or boost:shared_ptr or even in your case auto_ptr) which I favor more
I should probably be sleeping. Instead, I'm coding. Specifically, I've written The World's Worse Memory Allocator(TM). It's got an array of bytes (chars) to use for memory for stuff; it's got a list of used memory blocks; it's got an index to allocate memory from. It even allocates memory. Deallocates, not so much.
That shouldn't be a problem, though, as to the best of my knowledge, nothing is new'd outside of the array and list classes and the destructor for those is called the proper number of times.
Edit: The problem is, the program enters what appears to be an infinite loop somewhere in the c++ back-end code itself, shortly after the MemoryManager's destructor is called. In fact, if the MemoryManager is put inside the Try-Catch block, the program never makes it outside the Try-Catch block. I need to know why and how to fix it, please, thanks.
This is the main loop which is doing terribly important allocations:
int _tmain(int argc, _TCHAR* argv[])
{
MemoryManager memoryManager = MemoryManager(1024);
try
{
int * n;
for (int t = 0; t < 32; ++t)
{
n = (int*)memoryManager.Allocate(4);
}
} catch (char* str) { std::cout << str; }
return 0;
}
And the MemoryManager, in all it's newbie glory:
// A memory manager
#pragma once
#include "stdafx.h"
#include "Array.h"
#include "SmartPointer.h"
class MemBlock
{
public:
unsigned int Start;
unsigned int End;
MemBlock() { Start = 0; End = 0; }
MemBlock(unsigned int start, unsigned int end)
{
Start = start; End = end;
}
~MemBlock() { }
};
class MemoryManager
{
private:
Array<char> memory;
List<MemBlock> memBlocks;
int index;
public:
MemoryManager(unsigned int size)
{
memory = Array<char>(size);
memBlocks = List<MemBlock>(size / 24);
index = 0;
}
~MemoryManager() { }
void* Allocate(unsigned int size)
{
memBlocks.Add(&MemBlock(index, index + size));
void* r = (void*)(memory.insecureAccess + index);
index += size;
return r;
}
};
Thanks.
You don't seem to have asked a question here, but I'm going to point out a horrible flaw in your approach anyway :)
If you are planning to write a Deallocate(void*) method then you are going to struggle.
You can match the void* pointer against your memBlocks list to determine which MemBlock it is, but you will only be able to reduce index if that MemBlock happens to be the last one returned by Allocate otherwise it is just a free hole in your array.
For a basic solution to this you would need a list of the free blocks and you would take allocated blocks from that list, and add them back to the list when they were deallocated.
This approach is called a free list: http://en.wikipedia.org/wiki/Free_list
Solved - Error in ignorance; it was an indirect error. I was using "delete theArray;" in the Array destructor (Array also being the base class of List) when I should have been using "delete [] theArray". The pause is now gone and the problem seems solved. Thanks for your time.