[Digikam-devel] Re: delete does not reset the pointer in GCC (4.6.0)

Francesco R. francesco at pnpitalia.it
Wed Jun 15 13:32:47 BST 2011


On Wednesday 15 June 2011 11:55:50 Marcel Wiesweg wrote:
> > a few months ago, maybe 2 years.
> > I know that I always added
> > xyz = 0;
> > to my code before, but then it was removed again because it is not
> > neccessary with modern compilers (I don't know who said that).
> 
> When googling and reading through the usual sources (stackoverflow etc.) I
> see noone saying that any compiler sets a pointer to 0, I would even guess
> delete should _not_ change the value of the passed pointer unless the C++
> standard says so. There are the usual stories not to use raw pointers and
> use concepts to make sure you are always sure never to use deleted pointers
> again, but in the end, if you are playing with raw pointers (which we are
> doing still in too many areas IMO, but getting less) and need to delete and
> reuse the variable, be sure to set it to 0.
> 
> Marcel

Disclaimer I do know nothing of c++ remember? please do take it in account.

This excided my curiosity too, and I've booth gcc-4.5 and 4.6 installed so 
tested the program below.

As far as I can see gcc does nothing to put a 0 in the pointer, neither in 4.5 
version, it does add a check before the "delete" call to avoid deleting a 0 
pointer but nothing else.

you can search for label "startLookingAtMe" in the gimple code attached 
(gimple is a low level rappresentation of the code used by gcc internally)


#include <iostream>

/*
g++-4.5.2 -O0 -ggdb3 -fdump-tree-gimple a.cpp \
&& mv a.cpp.004t.gimple a.cpp.004t.gcc45.gimple
g++-4.6.0 -O0 -ggdb3 -fdump-tree-gimple a.cpp \
&& mv a.cpp.004t.gimple a.cpp.004t.gcc46.gimple

# to compare use:
sed -i -e 's:[0-9][0-9][0-9][0-9][0-9]:99999:g' a.*.gimple

NO CHANGES g++-4.6.0 -O0 -fno-delete-null-pointer-checks -ggdb3 -fdump-tree-
gimple a.cpp && mv a.cpp.004t.gimple a.cpp.004t.gcc46dncp.gimple
*/

using namespace std;

main()
{
	int * p;
	p= new (nothrow) int[2];
	p[0] = 1; p[1] = 2;
	for (int n=0; n<2; n++)
		cout << p[n] << ", ";
	cout << endl;
startLookingAtMe:
	delete[] p;
	p = 0; // omitting this crashes
	delete[] p;
	if (p) delete p;
endLookingAtMe:
	cout << (0/0); // my easy brakpoint
}

-------------- next part --------------
A non-text attachment was scrubbed...
Name: a.cpp
Type: text/x-c++src
Size: 738 bytes
Desc: not available
URL: <http://mail.kde.org/pipermail/digikam-devel/attachments/20110615/e5ff7ccb/attachment.cpp>
-------------- next part --------------
(static initializers for a.cpp) ()
{
  __static_initialization_and_destruction_0 (1, 65535);
}


void __static_initialization_and_destruction_0(int, int) (int __initialize_p, int __priority)
{
  void (*<Tbc>) (void *) __comp_dtor .0;

  if (__initialize_p == 1) goto <D.21277>; else goto <D.21278>;
  <D.21277>:
  if (__priority == 65535) goto <D.21279>; else goto <D.21280>;
  <D.21279>:
  std::ios_base::Init::Init (&__ioinit);
  __comp_dtor .0 = (void (*<Tbc>) (void *)) __comp_dtor ;
  __cxa_atexit (__comp_dtor .0, &__ioinit, &__dso_handle);
  goto <D.21282>;
  <D.21280>:
  <D.21282>:
  goto <D.21283>;
  <D.21278>:
  <D.21283>:
}


int main() ()
{
  void * D.21284;
  int * D.21285;
  bool D.21289;
  long unsigned int D.21291;
  long unsigned int D.21292;
  int * D.21293;
  int D.21294;
  struct basic_ostream & D.21295;
  int D.21305;
  int D.21306;

  {
    int * p;

    D.21284 = operator new [] (8, &nothrow);
    p = (int *) D.21284;
    *p = 1;
    D.21285 = p + 4;
    *D.21285 = 2;
    {
      int n;

      n = 0;
      goto <D.21290>;
      <D.21288>:
      D.21291 = (long unsigned int) n;
      D.21292 = D.21291 * 4;
      D.21293 = p + D.21292;
      D.21294 = *D.21293;
      D.21295 = std::basic_ostream<char>::operator<< (&cout, D.21294);
      std::operator<< <std::char_traits<char> > (D.21295, &", "[0]);
      n = n + 1;
      <D.21290>:
      D.21289 = n <= 1;
      if (D.21289 != 0) goto <D.21288>; else goto <D.21286>;
      <D.21286>:
    }
    std::basic_ostream<char>::operator<< (&cout, endl);
    startLookingAtMe:
    if (p != 0B) goto <D.21296>; else goto <D.21297>;
    <D.21296>:
    operator delete [] (p);
    goto <D.21298>;
    <D.21297>:
    <D.21298>:
    if (p != 0B) goto <D.21299>; else goto <D.21300>;
    <D.21299>:
    operator delete [] (p);
    goto <D.21301>;
    <D.21300>:
    <D.21301>:
    if (p != 0B) goto <D.21302>; else goto <D.21303>;
    <D.21302>:
    operator delete (p);
    goto <D.21304>;
    <D.21303>:
    <D.21304>:
    endLookingAtMe:
    D.21305 = 0 / 0;
    std::basic_ostream<char>::operator<< (&cout, D.21305);
  }
  D.21306 = 0;
  return D.21306;
}


std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const char*) [with _Traits = std::char_traits<char>] (struct basic_ostream & __out, const char * __s)
{
  struct basic_ios * __out.1;
  int (*__vtbl_ptr_type) (void) * D.21312;
  int (*__vtbl_ptr_type) (void) * D.21313;
  long int * D.21314;
  long int D.21315;
  long unsigned int D.21316;
  struct basic_ios * D.21317;
  size_t D.21319;
  streamsize D.21320;
  struct basic_ostream & D.21321;

  if (__s == 0B) goto <D.21309>; else goto <D.21310>;
  <D.21309>:
  __out.1 = (struct basic_ios *) __out;
  D.21312 = __out->_vptr.basic_ostream;
  D.21313 = D.21312 + -24;
  D.21314 = (long int *) D.21313;
  D.21315 = *D.21314;
  D.21316 = (long unsigned int) D.21315;
  D.21317 = __out.1 + D.21316;
  std::basic_ios<char>::setstate (D.21317, 1);
  goto <D.21318>;
  <D.21310>:
  D.21319 = std::char_traits<char>::length (__s);
  D.21320 = (streamsize) D.21319;
  std::__ostream_insert<char, std::char_traits<char> > (__out, __s, D.21320);
  <D.21318>:
  D.21321 = __out;
  return D.21321;
}


void std::basic_ios<_CharT, _Traits>::setstate(std::ios_base::iostate) [with _CharT = char, _Traits = std::char_traits<char>, std::ios_base::iostate = std::_Ios_Iostate] (struct basic_ios * const this, iostate __state)
{
  iostate D.21323;
  _Ios_Iostate D.21324;

  D.21323 = std::basic_ios<char>::rdstate (this);
  D.21324 = std::operator| (D.21323, __state);
  std::basic_ios<char>::clear (this, D.21324);
}


std::ios_base::iostate std::basic_ios<_CharT, _Traits>::rdstate() const [with _CharT = char, _Traits = std::char_traits<char>, std::ios_base::iostate = std::_Ios_Iostate] (const struct basic_ios * const this)
{
  iostate D.21326;

  D.21326 = this->D.18578._M_streambuf_state;
  return D.21326;
}


std::_Ios_Iostate std::operator|(std::_Ios_Iostate, std::_Ios_Iostate) (_Ios_Iostate __a, _Ios_Iostate __b)
{
  _Ios_Iostate D.21328;
  int __a.2;
  int __b.3;
  int D.21331;

  __a.2 = (int) __a;
  __b.3 = (int) __b;
  D.21331 = __a.2 | __b.3;
  D.21328 = (_Ios_Iostate) D.21331;
  return D.21328;
}


static size_t std::char_traits<char>::length(const std::char_traits<char>::char_type*) (const char_type * __s)
{
  size_t D.21333;

  D.21333 = __builtin_strlen (__s);
  return D.21333;
}


std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] (struct basic_ostream * const this, struct __ostream_type & (*<T318c>) (struct __ostream_type &) __pf)
{
  struct __ostream_type & D.21335;

  D.21335 = __pf (this);
  return D.21335;
}


std::basic_ostream<_CharT, _Traits>& std::endl(std::basic_ostream<_CharT, _Traits>&) [with _CharT = char, _Traits = std::char_traits<char>] (struct basic_ostream & __os)
{
  struct basic_ostream & D.21338;
  struct basic_ios * __os.4;
  int (*__vtbl_ptr_type) (void) * D.21340;
  int (*__vtbl_ptr_type) (void) * D.21341;
  long int * D.21342;
  long int D.21343;
  long unsigned int D.21344;
  struct basic_ios * D.21345;
  char_type D.21346;
  int D.21347;
  struct basic_ostream & D.21348;

  __os.4 = (struct basic_ios *) __os;
  D.21340 = __os->_vptr.basic_ostream;
  D.21341 = D.21340 + -24;
  D.21342 = (long int *) D.21341;
  D.21343 = *D.21342;
  D.21344 = (long unsigned int) D.21343;
  D.21345 = __os.4 + D.21344;
  D.21346 = std::basic_ios<char>::widen (D.21345, 10);
  D.21347 = (int) D.21346;
  D.21348 = std::basic_ostream<char>::put (__os, D.21347);
  D.21338 = std::flush<char, std::char_traits<char> > (D.21348);
  return D.21338;
}


char_type std::basic_ios<_CharT, _Traits>::widen(char) const [with _CharT = char, _Traits = std::char_traits<char>, char_type = char] (const struct basic_ios * const this, char __c)
{
  char_type D.21353;
  int D.21354;
  const struct __ctype_type * const D.21355;
  const struct ctype & D.21356;

  D.21354 = (int) __c;
  D.21355 = this->_M_ctype;
  D.21356 = std::__check_facet<std::ctype<char> > (D.21355);
  D.21353 = std::ctype<char>::widen (D.21356, D.21354);
  return D.21353;
}


const _Facet& std::__check_facet(const _Facet*) [with _Facet = std::ctype<char>] (const struct ctype * __f)
{
  const struct ctype & D.21362;

  if (__f == 0B) goto <D.21360>; else goto <D.21361>;
  <D.21360>:
  std::__throw_bad_cast ();
  <D.21361>:
  D.21362 = __f;
  return D.21362;
}


std::ctype<char>::char_type std::ctype<char>::widen(char) const (const struct ctype * const this, char __c)
{
  char D.21364;
  char_type D.21367;
  unsigned char __c.5;
  int D.21369;
  int (*__vtbl_ptr_type) (void) * D.21370;
  int (*__vtbl_ptr_type) (void) * D.21371;
  int (*__vtbl_ptr_type) (void) D.21372;
  int D.21373;

  D.21364 = this->_M_widen_ok;
  if (D.21364 != 0) goto <D.21365>; else goto <D.21366>;
  <D.21365>:
  __c.5 = (unsigned char) __c;
  D.21369 = (int) __c.5;
  D.21367 = this->_M_widen[D.21369];
  return D.21367;
  <D.21366>:
  std::ctype<char>::_M_widen_init (this);
  D.21370 = this->D.15545._vptr.facet;
  D.21371 = D.21370 + 48;
  D.21372 = *D.21371;
  D.21373 = (int) __c;
  D.21367 = OBJ_TYPE_REF(D.21372;this->6) (this, D.21373);
  return D.21367;
}


std::basic_ostream<_CharT, _Traits>& std::flush(std::basic_ostream<_CharT, _Traits>&) [with _CharT = char, _Traits = std::char_traits<char>] (struct basic_ostream & __os)
{
  struct basic_ostream & D.21376;

  D.21376 = std::basic_ostream<char>::flush (__os);
  return D.21376;
}


-------------- next part --------------
(static initializers for a.cpp) ()
{
  __static_initialization_and_destruction_0 (1, 65535);
}


void __static_initialization_and_destruction_0(int, int) (int __initialize_p, int __priority)
{
  void (*<Tbc>) (void *) __comp_dtor .0;

  if (__initialize_p == 1) goto <D.21292>; else goto <D.21293>;
  <D.21292>:
  if (__priority == 65535) goto <D.21294>; else goto <D.21295>;
  <D.21294>:
  std::ios_base::Init::Init (&__ioinit);
  __comp_dtor .0 = (void (*<Tbc>) (void *)) __comp_dtor ;
  __cxa_atexit (__comp_dtor .0, &__ioinit, &__dso_handle);
  goto <D.21297>;
  <D.21295>:
  <D.21297>:
  goto <D.21298>;
  <D.21293>:
  <D.21298>:
}


int main() ()
{
  int * D.21299;
  bool D.21303;
  long unsigned int D.21305;
  long unsigned int D.21306;
  int * D.21307;
  int D.21308;
  struct basic_ostream & D.21309;
  int D.21319;
  int D.21320;

  {
    int * p;

    p = operator new [] (8, &nothrow);
    *p = 1;
    D.21299 = p + 4;
    *D.21299 = 2;
    {
      int n;

      n = 0;
      goto <D.21304>;
      <D.21302>:
      D.21305 = (long unsigned int) n;
      D.21306 = D.21305 * 4;
      D.21307 = p + D.21306;
      D.21308 = *D.21307;
      D.21309 = std::basic_ostream<char>::operator<< (&cout, D.21308);
      std::operator<< <std::char_traits<char> > (D.21309, ", ");
      n = n + 1;
      <D.21304>:
      D.21303 = n <= 1;
      if (D.21303 != 0) goto <D.21302>; else goto <D.21300>;
      <D.21300>:
    }
    std::basic_ostream<char>::operator<< (&cout, endl);
    startLookingAtMe:
    if (p != 0B) goto <D.21310>; else goto <D.21311>;
    <D.21310>:
    operator delete [] (p);
    goto <D.21312>;
    <D.21311>:
    <D.21312>:
    p = 0B;
    if (p != 0B) goto <D.21313>; else goto <D.21314>;
    <D.21313>:
    operator delete [] (p);
    goto <D.21315>;
    <D.21314>:
    <D.21315>:
    if (p != 0B) goto <D.21316>; else goto <D.21317>;
    <D.21316>:
    operator delete (p);
    goto <D.21318>;
    <D.21317>:
    <D.21318>:
    endLookingAtMe:
    D.21319 = 0 / 0;
    std::basic_ostream<char>::operator<< (&cout, D.21319);
  }
  D.21320 = 0;
  return D.21320;
}


std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const char*) [with _Traits = std::char_traits<char>] (struct basic_ostream & __out, const char * __s)
{
  int (*__vtbl_ptr_type) (void) * D.21325;
  int (*__vtbl_ptr_type) (void) * D.21326;
  long int D.21327;
  long unsigned int D.21328;
  struct basic_ios * D.21329;
  size_t D.21331;
  streamsize D.21332;
  struct basic_ostream & D.21333;

  if (__s == 0B) goto <D.21323>; else goto <D.21324>;
  <D.21323>:
  D.21325 = __out->_vptr.basic_ostream;
  D.21326 = D.21325 + -24;
  D.21327 = MEM[(long int *)D.21326];
  D.21328 = (long unsigned int) D.21327;
  D.21329 = __out + D.21328;
  std::basic_ios<char>::setstate (D.21329, 1);
  goto <D.21330>;
  <D.21324>:
  D.21331 = std::char_traits<char>::length (__s);
  D.21332 = (streamsize) D.21331;
  std::__ostream_insert<char, std::char_traits<char> > (__out, __s, D.21332);
  <D.21330>:
  D.21333 = __out;
  return D.21333;
}


void std::basic_ios<_CharT, _Traits>::setstate(std::ios_base::iostate) [with _CharT = char, _Traits = std::char_traits<char>, std::ios_base::iostate = std::_Ios_Iostate] (struct basic_ios * this, iostate __state)
{
  iostate D.21335;
  _Ios_Iostate D.21336;

  D.21335 = std::basic_ios<char>::rdstate (this);
  D.21336 = std::operator| (D.21335, __state);
  std::basic_ios<char>::clear (this, D.21336);
}


std::ios_base::iostate std::basic_ios<_CharT, _Traits>::rdstate() const [with _CharT = char, _Traits = std::char_traits<char>, std::ios_base::iostate = std::_Ios_Iostate] (const struct basic_ios * this)
{
  iostate D.21338;

  D.21338 = this->D.18587._M_streambuf_state;
  return D.21338;
}


std::_Ios_Iostate std::operator|(std::_Ios_Iostate, std::_Ios_Iostate) (_Ios_Iostate __a, _Ios_Iostate __b)
{
  _Ios_Iostate D.21340;
  int __a.1;
  int __b.2;
  int D.21343;

  __a.1 = (int) __a;
  __b.2 = (int) __b;
  D.21343 = __a.1 | __b.2;
  D.21340 = (_Ios_Iostate) D.21343;
  return D.21340;
}


static std::size_t std::char_traits<char>::length(const char_type*) (const char_type * __s)
{
  size_t D.21345;

  D.21345 = __builtin_strlen (__s);
  return D.21345;
}


std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] (struct basic_ostream * this, struct __ostream_type & (*<T372f>) (struct __ostream_type &) __pf)
{
  struct __ostream_type & D.21347;

  D.21347 = __pf (this);
  return D.21347;
}


std::basic_ostream<_CharT, _Traits>& std::endl(std::basic_ostream<_CharT, _Traits>&) [with _CharT = char, _Traits = std::char_traits<char>] (struct basic_ostream & __os)
{
  struct basic_ostream & D.21350;
  int (*__vtbl_ptr_type) (void) * D.21351;
  int (*__vtbl_ptr_type) (void) * D.21352;
  long int D.21353;
  long unsigned int D.21354;
  struct basic_ios * D.21355;
  char_type D.21356;
  int D.21357;
  struct basic_ostream & D.21358;

  D.21351 = __os->_vptr.basic_ostream;
  D.21352 = D.21351 + -24;
  D.21353 = MEM[(long int *)D.21352];
  D.21354 = (long unsigned int) D.21353;
  D.21355 = __os + D.21354;
  D.21356 = std::basic_ios<char>::widen (D.21355, 10);
  D.21357 = (int) D.21356;
  D.21358 = std::basic_ostream<char>::put (__os, D.21357);
  D.21350 = std::flush<char, std::char_traits<char> > (D.21358);
  return D.21350;
}


std::basic_ios<_CharT, _Traits>::char_type std::basic_ios<_CharT, _Traits>::widen(char) const [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ios<_CharT, _Traits>::char_type = char] (const struct basic_ios * this, char __c)
{
  char_type D.21363;
  int D.21364;
  const struct __ctype_type * const D.21365;
  const struct ctype & D.21366;

  D.21364 = (int) __c;
  D.21365 = this->_M_ctype;
  D.21366 = std::__check_facet<std::ctype<char> > (D.21365);
  D.21363 = std::ctype<char>::widen (D.21366, D.21364);
  return D.21363;
}


const _Facet& std::__check_facet(const _Facet*) [with _Facet = std::ctype<char>] (const struct ctype * __f)
{
  const struct ctype & D.21372;

  if (__f == 0B) goto <D.21370>; else goto <D.21371>;
  <D.21370>:
  std::__throw_bad_cast ();
  <D.21371>:
  D.21372 = __f;
  return D.21372;
}


std::ctype<char>::char_type std::ctype<char>::widen(char) const (const struct ctype * const this, char __c)
{
  char D.21374;
  char_type D.21377;
  unsigned char __c.3;
  int D.21379;
  int (*__vtbl_ptr_type) (void) * D.21380;
  int (*__vtbl_ptr_type) (void) * D.21381;
  int (*__vtbl_ptr_type) (void) D.21382;
  int D.21383;

  D.21374 = this->_M_widen_ok;
  if (D.21374 != 0) goto <D.21375>; else goto <D.21376>;
  <D.21375>:
  __c.3 = (unsigned char) __c;
  D.21379 = (int) __c.3;
  D.21377 = this->_M_widen[D.21379];
  return D.21377;
  <D.21376>:
  std::ctype<char>::_M_widen_init (this);
  D.21380 = this->D.15550._vptr.facet;
  D.21381 = D.21380 + 48;
  D.21382 = *D.21381;
  D.21383 = (int) __c;
  D.21377 = OBJ_TYPE_REF(D.21382;this->6) (this, D.21383);
  return D.21377;
}


std::basic_ostream<_CharT, _Traits>& std::flush(std::basic_ostream<_CharT, _Traits>&) [with _CharT = char, _Traits = std::char_traits<char>] (struct basic_ostream & __os)
{
  struct basic_ostream & D.21386;

  D.21386 = std::basic_ostream<char>::flush (__os);
  return D.21386;
}


virtual const char_type* std::ctype<char>::do_narrow(const char_type*, const char_type*, char, char*) const (const struct ctype * const this, const char_type * __lo, const char_type * __hi, char D.15511, char * __dest)
{
  long int __hi.4;
  long int __lo.5;
  long int D.21391;
  long unsigned int D.21392;
  const char_type * D.21393;

  __hi.4 = (long int) __hi;
  __lo.5 = (long int) __lo;
  D.21391 = __hi.4 - __lo.5;
  D.21392 = (long unsigned int) D.21391;
  __builtin_memcpy (__dest, __lo, D.21392);
  D.21393 = __hi;
  return D.21393;
}


virtual char std::ctype<char>::do_narrow(std::ctype<char>::char_type, char) const (const struct ctype * const this, char_type __c, char D.15506)
{
  char D.21395;

  D.21395 = __c;
  return D.21395;
}


virtual const char* std::ctype<char>::do_widen(const char*, const char*, std::ctype<char>::char_type*) const (const struct ctype * const this, const char * __lo, const char * __hi, char_type * __dest)
{
  long int __hi.6;
  long int __lo.7;
  long int D.21399;
  long unsigned int D.21400;
  const char * D.21401;

  __hi.6 = (long int) __hi;
  __lo.7 = (long int) __lo;
  D.21399 = __hi.6 - __lo.7;
  D.21400 = (long unsigned int) D.21399;
  __builtin_memcpy (__dest, __lo, D.21400);
  D.21401 = __hi;
  return D.21401;
}


virtual std::ctype<char>::char_type std::ctype<char>::do_widen(char) const (const struct ctype * const this, char __c)
{
  char_type D.21403;

  D.21403 = __c;
  return D.21403;
}




More information about the Digikam-devel mailing list