I have to work and create often matrices(I have to use pointers) so I made a function in C++ to allocate space for them and also make sure that the last value is set to NULL.
The application drops this error(glibc detected: memory curruption) in a specific case. Here is the code:
template<typename T> T *allocate(int size) {
T *temp = new T[size];
temp[size] = (T) NULL;
return temp;
}
This works:
unsigned char *tmp = allocate <unsigned char> (10);
But this one drops the error:
unsigned char **tmp = allocate <unsigned char *> (10);
That would be the equivalent of:
unsigned char **tmp = new unsigned char *[10];
tmp[10] = (unsigned char *) NULL;
Which is good. Why would it drop me this error?
Update: Thanks for the responses. I am so blind. That's one bug. But the problem of the crash was from another part of the code but also because I was adding NULL outside the allocated space of the array.
You can't do this:
temp[size] = (T) NULL;
Size in this case is indexing the memory position AFTER the last one you allocated, change it for this:
temp[size-1] = (T) NULL;
temp[size] = (T) NULL;
is assigning to unallocated memory.
T *temp = new T[size];
allocates from temp[0] to temp[size-1]
Related
I'm working on an assignment which involves updating the size of a dynamic array to store repeated inputs, with a value of -1 signifying the end of input. When I use this code:
bool end = false;
int curr;
int n = 0;
int* currArr = new int[n];
int* temp = NULL;
while (end == false) {
cin >> curr;
if (curr == -1) {
end = true;
}
else {
n++;
int* temp = new int[n];
temp = currArr;
temp[n - 1] = curr;
currArr = temp;
}
}
delete[] currArr;
delete[] temp;
am I defining a memory address for temp, changing what is stored at that address during each iteration, then cleanly deleting the contents of that address at the end?
Or am I allocating a new dynamic array during each iteration, only deleting the array defined in the final iteration, and leaking the rest? If so, how would I avoid that?
Similarly, if I define a dynamic array within a function like so:
int* fxn(int size) {
int* x = new int[size];
return &x[0];
}
int main() {
int* y = fxn(size);
delete[] y;
return 0;
}
My understanding is that deleting y will delete the array because y is pointing to the same address that x pointed to within the function. If fxn were a void function, x would need to be deleted within fxn, because fxn would not output any information to the main with which to locate x.
Am I understanding it correctly?
Thanks!
Each time you allocate memory and assign your previous allocated pointer to the newly allocated memory, you should delete the previous one. Otherwise it results in a memory leak. In your case curArr keeps pointing to the new address in the loop but previous is never deleted. Then your delete of both curArr and temp will crash because they are pointing to the same location, so you're deleting the same pointer twice. And assinging temp to curArray after allocating it, you just lost the newly allocated pointer again. So the code is a giant mess that's full of leaks and crashes. You're also initially allocating a memory of size 0 which is undefined behavior.
#include <iostream>
#include <memory>
using namespace std;
int main(){
bool end = false;
int curr;
int n = 1;
int* currArr = new int[n];
while (end == false) {
cin >> curr;
if (curr == -1) {
end = true;
}
else {
currArr[n - 1] = curr;
int* temp = new int[n+1];
memcpy(temp, currArr, n*sizeof(int));
delete[] currArr;
currArr = temp;
++n;
}
}
for(int index = 0; index < n-1; ++index){
std::cout << currArr[index]<< std::endl;
}
delete[] currArr;
}
I got rid of redundancies in your code and fixed up the leaks.
The code will initially allocate memory with a size of n=1. Then whatever the user enters into curr will be placed at index n-1. Then new memory will be allocated using temp to size of n+1. The previous memory from curArr will be copied into the newly allocated region. The previous region of curArr will be deleted and the pointer will be assigned to the new region.
And yes. Your understanding of your second question is correct.
int* temp = new int[n];
This allocates a new int array, in dynamic scope, assigning the allocated array to temp. Immediately afterwards:
temp = currArr;
This takes the newly-allocated array, temp, and immediately overwrites this pointer with an existing pointer currArr. The newly-allocated memory is leaked, and when is all and said and done, both temp and currArr are now the same pointer value (the second assignment, two lines later, does not change this, it's already too late).
delete[] currArr;
delete[] temp;
Therefore, this ends up delete[] ing the same pointer value twice, resulting in undefined behavior, memory corruption, and a likely crash.
Additionally, even if the allocation in the loop is fixed so it doesn't get clobbered, since the loop can execute more than once, and this deletes anything only at the conclusion of the loop, there's no way to avoid leaking memory, in any case.
am I defining a memory address for temp, changing what is stored at
that address during each iteration, then cleanly deleting the contents
of that address at the end?
No, you're leaking memory, corrupting memory, and causing undefined behavior, and a likely crash.
You need to fix the initial allocation, so it doesn't get clobbered, and delete the previous buffer (currArray) immediately after allocating the new one (temp), and then, finally, assign temp to currArray (after copying its contents).
Because i don't know verry much about memory allocation, I would like to know if it safe to delete a block of consecutive bytes (array) like this.
void Free(void* ptr, size_t cbSize)
{
if (cbSize == 0) return;
if (ptr == NULL) return;
for(size_t i = cbSize; i > 0; i--)
{
char* p = &((char*)ptr)[i];
delete p;
}
char* p = (char*) (ptr);
delete p;
}
I have tried this method in the following circumstances and got no error.
int* a = new int[100];
Free(a, 100 * sizeof(int));
int* a = (int*) malloc(100 * sizeof(int));
Free(a, 100 * sizeof(int));
You always delete what you allocate; exactly and only what you allocate. If you new a single thing, you delete a single thing. The fact that the "single thing" happens to take up more than one byte is irrelevant; you delete what you new.
How can i make my function work in this case ?
You don't. You newed an array of ints. So you must delete an array of ints. Types matter in C++.
I have defined a list of pointers. How should I free all these pointers before clearing the list? What is the best approach to erase all list members? In below program, is it required to free memory allocated for struct?? See my inline comments.
struct MyStruct {
char *data;
int len;
};
typedef std::list<struct MyStruct *> myStruct_list;
myStruct_list l_list;
/* Prepare a list */
for( int i = 0; i < 10; i++) {
struct MyStruct *s = (MyStruct *)malloc(sizeof(struct MyStruct));
s->data = (char*)malloc(MAX_LEN);
get_random_data(s->data,size);
s->len = strlen(s->data);
l_list.push_back(s);
}
/* Delete all members from a list */
myStruct_list::iterator it;
for (it = l_list.begin(); it != l_list.end(); ++it) {
if (*it) {
free(*it); // --->> do I need to free (*it)->data ?????
}
}
l_list.clear();
I want to understand is there any memory leak in below program?
Yes you have it right here:
p = (char*)malloc(MAX_LEN);
p = (char *)buf;
you allocate memory and assign it to p and next line you loose it. So:
You should not use malloc() in C++ programs unless you need to pass data that would be managed by C code
You should use special data structure like std::string etc to manage your data.
If you still need to allocate dynamic memory use smart pointers.
How should I debug if there is any memory leak?
You would not create them in the first place. For example, how could you write get_random_str (assuming you really have to allocate it using malloc):
using spchar = std::unique_ptr<char[], decltype(std::free) *>;
spchar get_random_str( int len )
{
spchar s( static_cast<char *>( malloc( len + 1 ) ), std::free );
static const char alphanum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < len; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[len] = '\0';
return s;
}
Note, I did not compile this code, it's to show you the idea.
Update: looks like you think that this code:
p = (char *)buf;
would copy string from buf to p, which is not the case. Instead you make p point to memory of buf loosing old value that malloc() returned before (hence creating memory leak) and you assign that adress of buf to data which leads to UB when you call free() on it, so what you need instead:
strncpy( p, buf, MAX_LEN );
but even that is not necessary as you do not really need buf at all:
void myClass::fillData(void)
{
s = (MyStruct *)malloc(sizeof(struct MyStruct));
s->data = (char*)malloc(MAX_LEN);
get_random_str(s->data,950);
s->len = strlen(s->data);
l_list.push_back(s);
}
but this is more C code, using some C++ syntax. You should get newer compiler and textbook if you really want to learn C++.
Delete elements using lambda function in for_each:
std::for_each(l_list.begin(), l_list.end(), [](const MyStruct* elem){if(elem) free(elem)});
And clear pointers:
l_list.clear();
I've been working on a memory pool allocator class, and no major problems have arisen, sans Visual Studio's debug assertion (_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)) being thrown whenever I try to free the memory allocated by new with delete.
typedef uintptr_t uptr;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
struct FreeList
{
FreeList *next;
};
template<class T, u8 alignment, u32 poolSize>
class PoolAllocator
{
private:
u8 _paddedSize; // The size in bytes of each allocated chunk of memory.
u32 _numAllocations;// The number of allocations made by the pool.
u32 _freeBytes; // The number of bytes left in the pool.
u32 _usedBytes; // The number of bytes currently occupied in the pool.
FreeList* _freeListHead; // A pointer to a freed space in memory.
public:
PoolAllocator() :
_paddedSize((sizeof(T) > sizeof(uptr) ? sizeof(T) : sizeof(uptr))),
_numAllocations(0),
_freeBytes(0),
_usedBytes(0),
_freeListHead(nullptr)
{
_freeListHead = reinterpret_cast<FreeList*>(operator new (_paddedSize * poolSize));
_freeBytes = _paddedSize * poolSize;
uptr current = reinterpret_cast<uptr>(_freeListHead);
uptr last = current + (_paddedSize * poolSize);
for (int i = 0; i < poolSize-1; i++)
{
uptr next = current + _paddedSize;
(reinterpret_cast<FreeList*>(current))->next = reinterpret_cast<FreeList*>(next);
current += _paddedSize;
}
reinterpret_cast<FreeList*>(current)->next = nullptr;
}
T *allocate()
{
if (_freeListHead != nullptr && _freeBytes >= _paddedSize) // Make sure the pool has memory left
{
uptr *toReturn = reinterpret_cast<uptr*>(_freeListHead); // Cast the pointer to a modifiable data type.
_freeListHead = _freeListHead->next; // VITAL THAT THIS IS BEFORE SETTING DATA TO 0.
*toReturn = 0; // Set the data at the memory location to 0.
_freeBytes -= _paddedSize;
_usedBytes += _paddedSize;
_numAllocations++;
printf("Allocated %d bytes of memory at %p.\n", _paddedSize, toReturn);
return reinterpret_cast<T*>(toReturn);
}
else
{
printf("Pool allocator out of memory! Returning nullptr.\n");
return nullptr;
}
}
void free(T **ptr)
{
FreeList *newHead = reinterpret_cast<FreeList*>(*ptr);
*ptr = nullptr;
newHead->next = _freeListHead;
_freeListHead = newHead;
_freeBytes += _paddedSize;
_usedBytes -= _paddedSize;
_numAllocations--;
printf("Freed %d bytes of memory at %p.\n", _paddedSize, _freeListHead);
}
void clear()
{
assert(_usedBytes == 0);
FreeList *head = _freeListHead;
while (head != 0)
{
FreeList *next = head->next;
delete reinterpret_cast<T*>(head);
head = next;
}
_paddedSize = 0;
_numAllocations = 0;
_freeBytes = 0;
_usedBytes = 0;
_freeListHead = nullptr;
}
};
The test code I am using:
int main()
{
PoolAllocator<int, 4, 4> pool;
int *a, *b, *c, *d, *e;
a = pool.allocate();
b = pool.allocate();
c = pool.allocate();
d = pool.allocate();
pool.free(&a);
e = pool.allocate();
printf("A | %p\t%d\nB | %p\t%d\nC | %p\t%d\nD | %p\t%d\nE | %p\t%d\n", a, 0, b, *b, c, *c, d, *d, e, *e);
pool.free(&b);
pool.free(&c);
pool.free(&d);
pool.free(&e);
pool.clear();
return 0;
}
The problem area lies here:
void clear()
{
assert(_usedBytes == 0);
FreeList *head = _freeListHead;
while (head != 0)
{
FreeList *next = head->next;
delete reinterpret_cast<T*>(head); // Debug assert
head = next;
}
_paddedSize = 0;
_numAllocations = 0;
_freeBytes = 0;
_usedBytes = 0;
_freeListHead = nullptr;
}
What this code is supposed to do is increment through the linked list of memory locations where individual pieces of data of type T are being stored. My reasoning for this being a valid piece of code is that, because the initially allocated memory is divided into pieces the size of sizeof(T). Therefor, I assumed that it would be appropriate to typecast the memory address to a pointer of type T* so that the individual block of memory would be completely deallocated. This would be done for the entire linked list, ensuring that all allocated memory is freed. However, when I run the code, it always throws the assert on the delete.
Stepping through the code showed that after the first iteration of typecasting and deleteing, the pointers take on strange values (the next variable, for instance:
next 0x004b2864 {next=0xfeeefeee {next=??? } } FreeList *
Whereas before, it was
next 0x006c2864 {next=0x006c2860 {next=0x006c285c {next=0x00000000
} } } FreeList *
just as it should be). I have tried this approach many different times in many different ways, including typecasting to void* instead of T*.
This problem has had me stumped for days, and any help would be appreciated. Thank you.
reinterpret_cast<T*>(head)->~T();
I tested this and not getting the assert anymore by replacing delete reinterpret_cast(head);
You can't call delete on head because the memory wasn't allocated by calling new T();
This will not compile:
struct FreeList
{
FreeList *next;
};
... but the following will:
struct FreeList
{
struct FreeList *next;
};
Otherwise, an error about incomplete struct definition or unknown type FreeList will be raised by the compiler.
i am starting homework about dynamic array, first, I have a 2 dimensional array :
int initializeInfo[3][4] ={{77,68,0,0},{96,87,89,78},{70,90,86,0}};
and use pointer to store it:
int **ptr = (int**)malloc(3*sizeof(int));
int size = 0;
for(int i =0;i<3;i++){
addInitiazeInfo(ptr,initializeInfo[i],size);
}
here is function addInitiazeInfo:
void addInitiazeInfo(int**& ptr, int arr[],int& size){
ptr[size] = (int*)malloc(4*sizeof(int));
if(ptr[size] == NULL){
return;
}
ptr[size] = arr;
size++;
}
It's run OK! The 2 dimensional array is store by ptr pointer.
And I want to add new row, I think realloc is needed, then I try:
int arr[] = {3,4,5,6};
size++;
ptr = (int**)realloc(ptr,size * sizeof( int ) );
ptr[size-1] = (int*)malloc(4*sizeof(int));
ptr[size-1] = arr;
But I think this is my trouble, the output make me hard to know how it happend:
please help me, thanks everyone
When you do
ptr[size] = arr;
You are essentially assigning the address of arr, to ptr[size]. This means that the memory you just allocated is lost and successfully leaked.
You want to manually copy element by element or use something like memcpy. It is likely this might fix your issue, depending on the rest of your code.