0

Say that I want to allocate an array of ints.

int* array = new int[5];

and then later on assume I have 5 int pointers, all pointing to the 5 different integers of the array.

 int* v1 = &array[0];
 int* v2 = &array[1]; //etc..etc

Now that I have "remembered" the location of all the ints in the array, I would like to manage the elements as individual integers. So in theory if I then set my array pointer to NULL...

array = NULL;

I would in theory not have to worry, because all my v1 and v2 pointers are pointing to all the elements in the array. The problem then is say like I am done with v2. So I would like to delete v2 to free up those 4 bytes.

delete v2;

Unfortunately, when I try to do that, bad things happen. I assume because the memory allocation table says "Hey, you can't delete in that space because it currently belongs to part of an int array!"

So thats fine, I would then like to say

delete [] array;

but if I do that, I want to make sure that when I do...

int* v1 = new int;

I want to guarantee that the newly allocated integer was created at the address of array[0]. So is there a way to specify where a new value is created? Or can I somehow control the memory list?

I've attempted to use the placement operator by calling something like...

int* v1 = new((void*)&array[0]) int;

but then when I delete the array with the delete operator and then attempt to access v1 by dereferenceing it... say

cout<<*v1;

I get a bunch of text to the screen that says "double free or corruption (fasttop): ...

I am using Ubuntu 11.04 and g++ compiler in codeblocks.

Also, just FYI, I have looked at Create new C++ object at specific memory address? and that is where I got the information about the placement operator, but it appears to not be working the way I need it to work.

#include <iostream>

using namespace std;

int main()
{
int *array = new int[20];

for(int i=0;i<4;i++)
{
    array[i] = i;
}

int* a = new ((void*)&array[0]) int;
int* b = new ((void*)&array[1]) int;
int* c = new ((void*)&array[2]) int;
int* d = new ((void*)&array[3]) int;
int* e = new ((void*)&array[4]) int;

cout<<*a<<endl;
cout.flush();

delete[] array;

cout<<*a;

delete a;
delete b;
delete c;
delete d;
delete e;

return 0;
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Matthew
  • 3,886
  • 7
  • 47
  • 84
  • Oh by the way, I don't get the "double free or corruption" message on the cout, I get that when I try to delete a. – Matthew Mar 22 '12 at 03:30
  • 1
    It sounds like you really want to create a memory pool so that instead of deleting the variable in the array, you just mark it as invalid and then reuse it when you need a new allocation. – tpg2114 Mar 22 '12 at 03:31
  • By int* v1 = array[0]; did you actually mean int* v1 = &array[0];? int* v1 = array[0]; is a bit nonsensical when array[0] is an int. – Corbin Mar 22 '12 at 03:32
  • Why would you want to do this? What is the purpose? There may be a way to do it, but I don't see what you would gain by doing so. – aldo Mar 22 '12 at 03:33
  • Can you show how you're doing the deletes, i.e. actual full code? – Collin Dauphinee Mar 22 '12 at 03:35
  • @tpg2114 : Yeah, but in theory I will have a huge array, and I would like to free up chunks of that to be used by the OS for future variables. – Matthew Mar 22 '12 at 03:49
  • @Corbin : Yes, you are correct, I messed up the syntax there. – Matthew Mar 22 '12 at 03:49
  • @aldo : I would like to do this because I am creating a LinkedList class that you can freely insert and delete elements when you want, and then after a function call you can stack all the data in an array and access the elements in O(1) time. – Matthew Mar 22 '12 at 03:50
  • You should read about shared_ptr – nikhil Mar 22 '12 at 03:52
  • @nikhil : In this particular case I want to manage my own memory. I basically want to remove say the middle third of a huge array and allow that memory to be used again by other new variables. – Matthew Mar 22 '12 at 04:00
  • You are going to have to do your own memory management then (or find a library to handle it for you). Basically you'll allocate X bytes, and then track which bytes inside of those X are used. You'll only actually free the X bytes at the very end of use. The other 'freeing' will just unmarking them as used. Doing this efficiently will present a complex problem though. You're really probably better just copying the elements into an array. LinkedLists are not meant to be work like this anyway. (Have you considered just a vector by the way?) – Corbin Mar 22 '12 at 04:08

3 Answers3

0

A correction:

int *v1 = array[0];
int *v2 = array[1];

should be

int *v1 = array;
int *v2 = array + 1;

Also, if you allocate new int[5], you can only free the memory for the entire array and not for individual elements.

"I want to guarantee that the newly allocated integer was created at the address of array[0]"

If that is the case, why should you go for a newly allocated integer? Just assign array to v1 as shown above.

Agnel Kurian
  • 57,975
  • 43
  • 146
  • 217
0

Allocation of memory does not work the way you have used and neither can you release memory in the manner you are trying to.

A placement new "creates" an object at the given location by calling the constructor of the object but does not allocate memory and hence the memory used by placement new cannot be released by a delete. Memory should be pre-allocated before a call to placement new and the memory can be released based on how the pre-allocation was made.

Usage : Placement new. Also, I found an example from a blog (not mine): Placement new

Ram
  • 3,045
  • 3
  • 27
  • 42
0
delete v2;

You should not delete elements individually allocated with placement new, release all the memory at one time when you are finished with it, like this delete [] array; (for a more detailed explanation).

And updating your code:

#include <iostream>

using namespace std;

int main()
{
    int *array = new int[20];

    for(int i=0;i<5;i++) // Still leaves garbage in rest of array
    {
        array[i] = i; 
    }

    int* a = new (array) int; 
    // int* a = new(&array[0]) int;
    int* b = new (array + 1) int;
    int* c = new (array + 2) int;
    int* d = new (array + 3) int;
    int* e = new (array + 4) int;

    cout << *a << " " << *b << " " << *c << " " << *d << " " << *e << endl;

    delete[] array;
 }

Couple of pointers:

1) cout.flush(); is unnecessary because std::endl calls flush() already.

2) I see no reason why placement new should be used here, take a look at this SO question to see reasons why you should use it. In your above example, int array[5]; and int* a = array; would be fine. Also, in a linked list the idea is that elements can be easily inserted and removed, if you allocate an array, you cannot delete the array and expect to be able to use the memory afterward (that would result in UB). So you have to choose between using an array or linked list, you can't have both (well, you could simulate a linked list to a certain extent).

3) Like I mentioned above, call delete [] array; after you are finished using the memory and do not dereference pointers into that memory or call delete on pointers into that memory once you have freed the memory.

Community
  • 1
  • 1
Jesse Good
  • 50,901
  • 14
  • 124
  • 166