Is it safe to delete a void* byte by byte? - c++

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++.

Related

How to allocate and deallocate an array of function pointers and keep valgrind happy?

How can I allocate and deallocate an array of function pointers in C++? I've tried two different strategies, first using single pointers and the second using double pointers but I can't seem to make valgrind happy. Here is my situation:
// function pointer
typedef double(*function_ptr)(double);
// function that adhers to the interface set by function_ptr
double do_nothing(double x) {
return x;
}
// dynamically create array of #param size function pointers, all pointing to do_nothing
function_ptr **make_function_ptr(int size) {
function_ptr xp = &do_nothing_transform;
function_ptr* xpp = &xp;
auto **trsfm = (ESfcnTrsfm **) malloc(sizeof(function_ptr *));
for (int i = 0; i < size; i++) {
trsfm[i] = (ESfcnTrsfm*) malloc(sizeof(function_ptr));
trsfm[i] = xpp; // same as trsfm[i] = ...
}
return trsfm;
}
// free the array of function pointers
void free_function_ptr(function_ptr **fun, int size) {
for (int i=0; i<size; i++){
free(fun[i]);
fun[i] = nullptr;
}
free(fun);
fun = nullptr;
}
Your make_function_ptr function allocates space for only one function_ptr in the 'outer' table, rather than allocating space for size pointers. So, this:
auto **trsfm = (ESfcnTrsfm **) malloc(sizeof(function_ptr *));
Should be:
auto **trsfm = (ESfcnTrsfm **) malloc(sizeof(function_ptr *) * size); // Need to multiply by "size"
Without this, the trsfm[i] access in the subsequent for loop is undefined behaviour, when i is anything other than zero.
Furthermore (as pointed out in the comments), you are allocating memory in that for loop unnecessarily. You need only assign the address of the dummy routine to the allocated table entries:
for (int i = 0; i < size; i++) {
// trsfm[i] = (ESfcnTrsfm*) malloc(sizeof(function_ptr)); // Unnecessary!
trsfm[i] = xpp; // same as trsfm[i] = ...
}
(And, similarly, you don't need the for loop to free those pointers in your free_function_ptr function.)
This line is obviously wrong:
auto **trsfm = (ESfcnTrsfm **) malloc(sizeof(function_ptr *));
You need to allocate that multiplied by "size".

Clear out the STL list of pointers 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();

realloc pointer change when out of function

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.

glibc detected memory curruption

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]

Program crash on array index assignment

I'm having a little problem here.
Every time I run the code below, my program just crash.
void Wingcod::push(byte b)
{
stack[stackp] = b;
stackp++;
if(stackp >= stacks)
{
stacks += 16;
try
{
realloc(stack,stacks);
}catch(bad_alloc*)
{
cerr << "STACK OVERFLOW";
exit(1);
}
}
}
And stack, stackp and stacks is defined like this:
stacks = 8;
stackp = 0;
stack = new byte[stacks];
And byte is just a unsigned char.
You're not allowed to use realloc() on a pointer that was allocated with new.
Maybe try something like the following instead of realloc():
byte* tmp = new byte[stacks];
delete [] stack;
stack = tmp;
realloc doesn't throw exceptions as it's not related to new, but C's malloc. It also doesn't set the pointer.
stacks = 8;
stackp = 0;
stack = static_cast<byte*>(malloc(stacks * sizeof(byte)));
void Wingcod::push(byte b)
{
stack[stackp] = b;
stackp++;
if(stackp >= stacks)
{
stacks += 16;
if(!(stack = static_cast<byte*>(realloc(stack,stacks * sizeof(byte))))) {
cerr << "STACK OVERFLOW";
exit(1);
}
}
}
You cannot use a pointer allocated with new T[n] as an argument for realloc(). The pointers working with realloc() have to come from the malloc() family of functions (malloc(), calloc(), or realloc()). Personally, I wouldn't use any of this but rather use std::vector<T>.
From here, Realloc only works on a pointer to memory previously assigned by alloc. Try using malloc