LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Implementation of free in C++11 using GNU's g++ 4.8.2 (https://www.linuxquestions.org/questions/programming-9/implementation-of-free-in-c-11-using-gnus-g-4-8-2-a-4175504114/)

ejspeiro 05-06-2014 02:32 PM

Implementation of free in C++11 using GNU's g++ 4.8.2
 
Dear all,

I have been constructing a code (for a while now), and for the sake of learning I tried to have this code using features from C++11.

I have many, many questions, however, for the sake of being concise I will start with the one in the subject line:

If I do:

Code:

double* ptr {};
Then ptr gets initialized to nullptr. What if I calloc it, and then I free it?

Does the free routine initialize a pointer to nullptr?

Thanks,

a4z 05-06-2014 02:46 PM

you do not call malloc / free in C++
use new and delete,
or better, unique_ptr or shared_ptr
feed the search machine of your choice with these keywords

mina86 05-06-2014 05:11 PM

No. Neither free nor delete will set the variable to NULL. If you care about the value you need to set it yourself.

ejspeiro 05-06-2014 08:16 PM

Dear a4z:

Thanks for your prompt reply. I want to learn. It is my biggest motivation to be alive :) Which is why I created this example, so that you guys can help me learn, so I can then help others learn :) :)

I love Valgrind's memcheck utility. I think it is pretty useful. In fact, in my makefiles, I have:

Code:

MEMCHECK_OPTS = -v --tool=memcheck --leak-check=yes
memcheck:
        valgrind $(MEMCHECK_OPTS) ./$(EXE) >& memcheck.txt

So that, as I code, I check for leaks through make memcheck :)

I have noticed, that when I do new, instead of malloc or calloc, I get that Valgrind reports errors.

Take this code:

Code:

#include <iostream>

using namespace std;

int main () {

  double *ptr;

  cout << "Valgrind, malloc, calloc, and new..." << endl;

  ptr = (double*) NULL;
  ptr = (double*) malloc(10*sizeof(double));
  for (auto ii = 0; ii < 10; ii++) {ptr[ii] = ii;}
  for (auto ii = 0; ii < 10; ii++) {cout << ptr[ii] << endl;}
  free(ptr);
  cout << endl;

  ptr = (double*) NULL;
  ptr = (double*) calloc(10,sizeof(double));
  for (auto ii = 0; ii < 10; ii++) {ptr[ii] = ii;}
  for (auto ii = 0; ii < 10; ii++) {cout << ptr[ii] << endl;}
  free(ptr);
  cout << endl;

  ptr = nullptr;
  ptr = new double[100];
  for (auto ii = 0; ii < 10; ii++) {ptr[ii] = ii;}
  for (auto ii = 0; ii < 10; ii++) {cout << ptr[ii] << endl;}
  delete ptr;
  cout << endl;
}

When I run

Code:

valgrind -v --tool=memcheck --leak-check=yes ./memtest
This is what I get (skipping the first 87 lines):

Code:

...
Valgrind, malloc, calloc, and new...
--3635-- REDIR: 0x51be590 (malloc) redirected to 0x4c2ab10 (malloc)
--3635-- REDIR: 0x51cf900 (strchrnul) redirected to 0x4c319b0 (strchrnul)
--3635-- REDIR: 0x51c7a50 (memchr) redirected to 0x4c2f390 (memchr)
0
1
2
3
4
5
6
7
--3635-- REDIR: 0x51cd5c0 (__GI_memcpy) redirected to 0x4c2fc90 (__GI_memcpy)
8
9
--3635-- REDIR: 0x51bec30 (free) redirected to 0x4c2bd80 (free)

--3635-- REDIR: 0x51bf060 (calloc) redirected to 0x4c2cbf0 (calloc)
0
1
2
3
4
5
6
7
8
9

--3635-- REDIR: 0x4e96020 (operator new[](unsigned long)) redirected to 0x4c2b790 (operator new[](unsigned long))
0
1
2
3
4
5
6
7
8
9
--3635-- REDIR: 0x4e94260 (operator delete(void*)) redirected to 0x4c2c250 (operator delete(void*))
==3635== Mismatched free() / delete / delete []
==3635==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3635==    by 0x400C2A: main (memtest.cc:29)
==3635==  Address 0x5a1d160 is 0 bytes inside a block of size 800 alloc'd
==3635==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3635==    by 0x400BA0: main (memtest.cc:26)
==3635==

==3635==
==3635== HEAP SUMMARY:
==3635==    in use at exit: 0 bytes in 0 blocks
==3635==  total heap usage: 3 allocs, 3 frees, 960 bytes allocated
==3635==
==3635== All heap blocks were freed -- no leaks are possible
==3635==
==3635== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==3635==
==3635== 1 errors in context 1 of 1:
==3635== Mismatched free() / delete / delete []
==3635==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3635==    by 0x400C2A: main (memtest.cc:29)
==3635==  Address 0x5a1d160 is 0 bytes inside a block of size 800 alloc'd
==3635==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3635==    by 0x400BA0: main (memtest.cc:26)
==3635==
==3635== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Could anybody explain why to me?

Thanks!

ejspeiro 05-06-2014 08:18 PM

Dear mina86:

Thanks for your answer! I will keep that in mind.

NevemTeve 05-06-2014 10:34 PM

You might clear the memory after 'new':

Code:

  int n= 100;
  ptr = new double[n];
  memset (ptr, 0, sizeof (ptr[0])*n);

Note: if you want to set ptr to NULL, do it right after free/delete, not right before malloc/new, that' pointless.

ejspeiro 05-06-2014 10:42 PM

Quote:

Originally Posted by NevemTeve (Post 5166075)
Note: if you want to set ptr to NULL, do it right after free/delete, not right before malloc/new, that' pointless.

I know that. The reason I do it, is because I have found that if I do not, Valgrind's memcheck complains of the pointer being used without initialization. I do it just to please memcheck.

Now, your suggestion to clear the memory... does it have to do with my post regarding memcheck's error related to the use of new?

Thanks!

a4z 05-07-2014 02:19 AM

ejspeiro, you are mixing C code with C++.
this is technical possible, and sometimes required.
but if you want to learn C++ you should learn modern C++, and not the old style C++ that every one wants to get rid of.

go there
http://msdn.microsoft.com/en-us/library/hh279654.aspx
and read.
keep an eye on Object Lifetime And Resource Management (Modern C++).

search also for othe resources in the internet.
good luck.

NevemTeve 05-07-2014 04:32 AM

> > If you want to set ptr to NULL, do it right after free/delete, not right before malloc/new, that' pointless.

> I know that. The reason I do it, is because I have found that if I do not, Valgrind's memcheck complains of the pointer being used without initialization. I do it just to please memcheck.

Just try what I've suggested.
Code:

Before:
free(ptr);
...
ptr= NULL;
ptr= malloc (size);

After:
free(ptr);
ptr= NULL;
...
ptr= malloc (size);

> Now, your suggestion to clear the memory... does it have to do with my post regarding memcheck's error related to the use of new?

It might. You could simply try it.

mina86 05-07-2014 09:37 AM

If you allocate an array using new, as in “new double[100]”, you must use delete[] to free the memory.

Also, you should avoid using sizeof with a type. What if you change type of the pointer to be float* and forget to change the type in sizeof? (Worse yet, what if you change to long double*). Instead use sizeof with an expression as an argument, for example:

Code:

ptr = (double *)malloc(10 * sizeof *ptr);
But as it has been mentioned, it's actually even better if you stick to new since it will do what you need, you won't have to cast the return type, and if you change pointer type but forget to change type in new invocation, you'll get compiler error.

ejspeiro 05-07-2014 10:04 AM

Wow! Thank you guys for all of your help :) I will try to give an answer to everyone of you :) (It may take some time, but I will)

Let me get myself started!

ejspeiro 05-07-2014 10:11 AM

Quote:

Originally Posted by a4z (Post 5166121)
ejspeiro, you are mixing C code with C++.
this is technical possible, and sometimes required.
but if you want to learn C++ you should learn modern C++, and not the old style C++ that every one wants to get rid of.

go there
http://msdn.microsoft.com/en-us/library/hh279654.aspx
and read.
keep an eye on Object Lifetime And Resource Management (Modern C++).

Dear a4z: you are right. In fact, I have taken a good read to the recommended website, and it does look amazing! I will read it profusely!

Just to clarify: The only reason I am doing double* and not something else, is due to the fact that I need to use the Netlib libraries. Basically, due to C++-Fortran interoperability. Granted: there must be a better way to achieve this, using smart pointers, for example! I'll make sure that learning that be a part of my goal regarding learning modern C++.

ejspeiro 05-07-2014 10:29 AM

Quote:

Originally Posted by mina86 (Post 5166348)
If you allocate an array using new, as in “new double[100]”, you must use delete[] to free the memory.

Also, you should avoid using sizeof with a type. What if you change type of the pointer to be float* and forget to change the type in sizeof? (Worse yet, what if you change to long double*). Instead use sizeof with an expression as an argument, for example:

Code:

ptr = (double *)malloc(10 * sizeof *ptr);
But as it has been mentioned, it's actually even better if you stick to new since it will do what you need, you won't have to cast the return type, and if you change pointer type but forget to change type in new invocation, you'll get compiler error.

Dear mina86: Nice! Thanks! This did fix my memcheck error! I feel I should apologize, since this is a well-known fact, about C++! Thanks for bringing it up!

You second comment has actually brought me on track to fully adopt new and delete[] :)

ejspeiro 05-07-2014 10:31 AM

Quote:

Originally Posted by NevemTeve (Post 5166168)
> > If you want to set ptr to NULL, do it right after free/delete, not right before malloc/new, that' pointless.

> I know that. The reason I do it, is because I have found that if I do not, Valgrind's memcheck complains of the pointer being used without initialization. I do it just to please memcheck.

Just try what I've suggested.
Code:

Before:
free(ptr);
...
ptr= NULL;
ptr= malloc (size);

After:
free(ptr);
ptr= NULL;
...
ptr= malloc (size);

> Now, your suggestion to clear the memory... does it have to do with my post regarding memcheck's error related to the use of new?

It might. You could simply try it.

Dear NevemTeve: Thanks for your suggestions :) I gave it a try, but I see not difference in the memcheck's output file... Am I missing something?

Thanks!

PS: I will be in Budapest from June, 1st to the 6th attending this event! Let me know if you want to connect! \m/

NevemTeve 05-07-2014 11:19 AM

Well, the problem was mixing new [] with delete (instead of delete [])

Clearing the malloc-ed/new-ed memory still might be a good idea, as valgind seems to read your memory-areas, so non-initialized memories might cause false valgrind messages.


All times are GMT -5. The time now is 01:33 PM.