Why am I getting EXC_BAD_ACCESS with these c++ functions? - c++

I am doing a homework assignment and I am running into these issues.
I am getting EXC_BAD_ACCESS when I call allocate();
void* Pool::allocate() {
if( free == NULL) {
this->expandPool();
}
void* tmp = free;
void* mem = malloc(elemSize);
memcpy(&free,free,sizeof(char*)); //exec bad access right here
memcpy(tmp,mem,sizeof(elemSize));
return tmp;
}
Here is my expandPool method:
void Pool::expandPool() {
poolSize++;
// Is this the first time?
if(poolSize <= 1)
pool = new char*[poolSize];
else {
char** tmp = new char*[poolSize];
memcpy(tmp,pool,sizeof(pool));
delete [] pool;
pool = tmp;
delete [] tmp;
}
char* tmp = NULL;
char* tmp2;
for(int i = 0; i < blockSize; i++) {
tmp2 = new char;
memcpy(tmp2,&tmp,sizeof(char*));
tmp = tmp2;
}
pool[poolSize - 1] = tmp;
free = tmp;
}

If you google EXC_BAD_ACCESS, you will find that it is because you are accessing memory outside an allocated memory block. This can be for several reasons.
So, lets start at the failing point -- the memcpy: you are writing to the free pointer (&free) the content of free (free), and are copying sizeof(char *) bytes. Assuming free is declared as char *free; then that is ok, so it must be the content of free you are writing from.
Stylistically, using memcpy like this -- to copy a single pointer value -- is confusing. You are better off with something like:
free = *(char **)free;
which is equivalent to your:
memcpy(&free,free,sizeof(char*));
The value of sizeof(char*) varies between systems -- 4 on 32-bit and 8 on 64-bit -- so the amount of space allocated must be at least that big.
Ok, so lets look at the expandPool method to see what free is set to:
tmp2 = new char;
Here, you are allocating a block of memory with sizeof(char) which is 1. This needs to be at least:
tmp2 = new char[sizeof(char *)];
NOTE: Calling your variable free will override the free function, so you will need to explicitly access that function by writing ::free.
I'd start off by drawing a diagram of what you want the memory layout of the pool to be and how it will look/change (a) when empty, (b) when allocating a chunk that is free and (c) when allocating a chunk when you need to expand the pool. Annotate the diagram with the different variables (pool, tmp, tmp2 and free). This will give you an idea of what you need to do and what the code should look like.
Having a good understanding of the data structures and algorithms (through creating the diagrams) will help you get the code right.

There are several problems in your code. One that stands out to me is this part:
pool = tmp;
delete [] tmp;
To me, this makes pool point to deleted memory. Using pool later in the code causes undefined behavior, which can not be explained by the language. Failure elsewhere in the code is just to be expected.

Related

C++ Custom memory management using brk() system call to allocate memory?

I wrote a basic custom memory management allocator which would grab a chunk of memory, pre-create X objects so that whenever I needed to "create" an object I could grab one of the pre-created ones and simply assign data members (memory was already allocated).
I used placement-new:
//Grab a chunk of memory
char* buf = new char [sizeof(X) * num_objs];
//Pre-create a lot of objects
for(std::int64_t i=0; i<num_objs; i++){
char* c = buf + (sizeof(X) * i);
//This line creates the Order object at location c
X* x = new(c)X;
}
//Assign data members to objects
for(std::int64_t i=0; i<num_objs; i++){
char* buf_loc = buf + (sizeof(X) * i);
X* my_x = reinterpret_cast <X*> (buf_loc);
my_x->a = 1;
my_x->b = 2;
my_x->c = 3;
my_x->d = 4;
}
How easy/practical would it be to change the above and directly grab memory from the OS using brk()?
Using brk will probably interfere with the regular C/C++ memory allocator. Even if you don't use regular new or malloc() in your code, it might be used in libraries.
If you want to manage your own memory, use mmap() on /dev/zero to get an empty block of memory. I think you can do this repeatedly to get new blocks.

Should I be using Malloc? Errors with large array of objects

I'm using a bit of legacy type code that runs on a framework, so I can't really explain whats going on at a lower level as I don't know.
However my code creates an array of objectives.
int maxSize = 20;
myObjects = new Object*[maxSize+1];
myObjects[0] = new item1(this);
myObjects[1] = new item2(this);
for(int i=2; i != maxSize+1; i++){
myObjects[i] = new item3(this);
}
myObjects[maxSize+1] = NULL;
If maxSize is larger than 30 I get a whole load of errors I've never seen. Visual Studio draws up an error in xutility highlighting:
const _Container_base12 *_Getcont() const
{ // get owning container
return (_Myproxy == 0 ? 0 : _Myproxy->_Mycont);
}
I've never used Malloc before, but is this where the problem lies. Should I be assigning using it to avoid this problem?
The absolute value of maxSize is probably not a culprit: allocating 30 pointers should go without trouble on any computer, including most micro-controllers. Using malloc is not going to change anything: you are doing your allocation the way you're supposed to do it in C++.
Here is the likely source of your error:
myObjects[maxSize+1] = NULL;
You have allocated storage for maxSize+1 items, so the valid indexes are between 0 and maxSize. Writing one past the last element is undefined behavior, meaning that a crash could happen. You got lucky with 20 elements, but 30 smoked out this bug for you. Using valgrind utility is a good way to catch memory errors that could cause crashes, even if they currently don't cause them.
int maxSize = 20;
myObjects = new Object*[maxSize+1];
myObjects[0] = new item1(this);
myObjects[1] = new item2(this);
// if maxsize is 1, this loop could be trouble
for(int i=2; i != maxSize; i++){
myObjects[i] = new item3(this);
}
myObjects[maxSize] = NULL;
You're going past the bounds with:
myObjects[maxSize+1] = NULL;
In your example, you created an array with 21 items. That will run from 0..20 but you're trying to write to the 21st element here.
The problem is not with new / delete as far as I can see, and I can't see any reason for switching to malloc here.
You should not use malloc() in C++; you should use new.
There's one possible exception to this: if you have to allocate a block of memory which you intend to pass as an argument to a function which is going to eventually free it using free(). If you used new to allocate such a block the free() would likely cause heap corruption. But this is purely hypothetical -- I've never seen such an API!
I think you can't access offset "maxSize+1". The solution is like:
myObjects = new Object*[maxSize+2];
...
myObjects[maxSize+1] = NULL;

Pointers pointing contiguous memory

Consider the following code
struct foo
{
const int txt_len;
const int num_len;
char * txt;
int * num;
foo(int tl, int nl): txt_len(tl), num_len(nl)
{
char * tmp = new char[txt_len * sizeof(char) + num_len * sizeof(int)];
txt = new (tmp) char [txt_len * sizeof(char)];
num = new (tmp + txt_len * sizeof(char)) int[num_len * sizeof(int)];
// is this the same as above?
// txt = tmp;
// num = (int *) (tmp + txt_len * sizeof(char));
}
~foo()
{
delete[] txt; // is this the right way to free the memory?
}
};
I want *txt and *num to be contiguous, is that the best way to do it?
also is there any difference between placement new and pointer arithmetic? which one should I use?
If you want a contiguous block of memory, you have to allocate it whole with a single call to operator new[] or malloc() or similar. Multiple calls to these functions do not guarantee any contiguity of allocated blocks whatsoever. You may allocate a big block and then carve parts from it as needed.
And you should delete and free() all blocks previously allocated with new and malloc(), otherwise you'll leak memory and probably make your program unstable (it will fail to allocate more memory at some point) and exert unnecessary pressure on memory in the OS, possibly slowing down other programs or making them unstable as well.
Placement new, however, does not actually allocate any memory. It simply constructs an object at the specified location and so you don't need to free that memory twice.
One problem that I see in your code is that it doesn't align ints. On some platforms reading or writing integers bigger than 1 byte from/to the memory must be aligned and if it's not, you can either read/write values from/to wrong locations or get CPU exceptions leading to termination of your program. The x86 is very permissive in this regard and won't mind, though may tax you with degraded performance.
You'll need to put the int data first, due to the alignment issues. But we can't then do delete num[] as the type is wrong - it must be cast to a char* before deleting.
char * tmp = new char[num_len * sizeof(int) + txt_len * sizeof(char)];
num = new (tmp) int[num_len];
txt = new (tmp + num_len * sizeof(int)) char [txt_len];
(This makes liberal use of the fact that sizeof(char)==1)
You might be tempted to do delete[] num, but num is of type int*, and it was new'ed as a char*. So you need to do;
delete[] (char*) num;
This is the same as long as you use POD types. And your delete is fine.
However, as David's comment states, you need to consider alignment problems.
Placement new is mostly use when you want to call constructor of class/struct on some preallocated memory blocks.
But for native types it makes no different to use placement new & pointer arithmetic.
Please correct me if I was wrong.
If txt and num always point to int and char, other built in types or other types not requiring construction, then no. You don't need placement new.
If on the other hand you were to change one of them to a class which requires construction, i.e. changes txt to type std::string, then using placement new is necessary.
Placement new allows you to call the constructor, building, if you like, the object at that address. Built in types have default constructors that do nothing if your not initializing.
In both cases you need to do pointer arithmetic, just one way you store the answer in a pointer, the other you pass the answer to placement new which gives it back to you for storage in the pointer, and then calls the constructor.

How to use delete[] when pointer outside memory allocation?

Note that the question has been changed and no longer matches the answers
I'm trying to create memory to hold a buffer of floats (here, 4 floats).
I've allocated the memory, and all the 4 values in the memory are zero.
The loop of course iterates 4 times, but the 4th time moves ptr to outside the memory that I've allocated. So at the end of the loop I move ptr back to where I allocated the memory, and use delete[].
My question is: Is the entire 4-float buffer being deleted when I call delete[]? (this is obviously what I need!)
int inFramesToProcess = 4;
float *ptr = new float[inFramesToProcess]();
for(UInt32 i = 0; i < inFramesToProcess; ++i) {
ptr++;
}
ptr -= inFramesToProcess;
delete[] ptr;
Copy the pointer before you increment it.
int inFramesToProcess = 4;
float *ptr = new float[inFramesToProcess]();
float *ptr_copy = ptr;
for(UInt32 i = 0; i < inFramesToProcess; ++i) {
ptr_copy++;
}
delete[] ptr;
Or just don't use pointers for dynamic arrays, use a vector instead. Then you don't have to worry about deleting.
You can't.
You can only delete the value you get from new. Keep the original pointer.
General rule:
Try hard to avoid modifying pointers at all times, no matter how clever/professional/"brilliant" it looks. There's really no reason to (you're welcome to prove me wrong). Use subscripts instead; they're more readable and easier to debug, and they avoid these kinds of issues.

delete[] and memory leaks

I am wondering about the delete[] operator in C++. (I am using Visual Studio 2005).
I have an unmanaged DLL that is being called by a managed DLL. When I close this program after performing a few tasks while debugging, I am getting many (thousands?) of memory leaks, mostly 24 bytes - 44 bytes in size.. I suspect it might be due to a certain unmanaged DLL I have.
Anyway, from what I understand, if I have the following code:
char* pointer = new char[500]
/* some operations... */
delete[] pointer;
Then all the memory for it is freed up correctly, am I right?
What happens when I have the following code:
char* pointer = new char[500];
char* pointerIt = pointer;
/* some code perhaps to iterate over the whole memory block, like so */
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointer;
The memory pointed to by pointer is deleted right? So it means that pointerIt is now not pointing to valid memory.. But that's ok because I can set both pointers to NULL, right?
Anyway, what happens now if I do this:
char* pointerFirstPosition = new char[500];
char* pointerIt = pointerFirstPosition;
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointerIt; // delete the pointer iterator...
Will this code delete the memory block pointed to by pointerIt up to pointerIt +500? or will it delete the memory block pointed to by pointerFirstPos to pointerFirstPos +500?
Could this result in a memory leak?
Sorry for the long winded message, I'm trying to get my message across clearly.
Thanks,
kreb
First question set:
char* pointer = new char[500]
/* some operations... */
delete[] pointer;
Then all the memory for it is freed up
correctly, am I right?
right.
Second question set:
char* pointer = new char[500];
char* pointerIt = pointer;
/* some code perhaps to iterate over the whole memory block, like so */
for (int i = 0; i < 250; i++){ // only iterate halfway
*pointerIt = 0;
pointerIt++;
}
delete[] pointer;
The memory pointed to by pointer is
deleted right? So it means that
pointerIt is now not pointing to valid
memory.. But that's ok because I can
set both pointers to NULL, right?
The memory pointer holds an address to is fully delted yes. Both pointer and pointerIt hold an address to invalid memory. Each pointer is simply a variable, and every variable is independent. So both store their own address independent of each other. The dereference operator * will simply give you the variable at that address. The variable at that address is a different variable than the pointer variable.
Third question set:
You should be deleting only the address that was allocated, the whole array. You'll have undefined results if you try to delete a partial array. Could it result in a memory leak? Possibly, could it result in a crash? Possibly, could it result in ....? Possibly.
So only delete what you allocate. If you allocate an array then you delete with delete[] if you delete a type that is not an array you delete with delete.
Here is an eample of something that is fine just for clarity:
char* pointer = new char[500];
char* pointerIt = pointer;
//This is fine because you are deleting the same address:
delete[] pointerIt;
//The memory that both variables point to is freed, do not try to free again
check out boost::shared_ptr or boost::scoped_ptr and NEVER worry about this again.
This gives you a static & reference counted way to manage your memory.
http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm