亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: 析構(gòu)函數(shù)內(nèi)存釋放問題 [打印本頁]

作者: tianhailong    時間: 2015-09-30 19:02
標(biāo)題: 析構(gòu)函數(shù)內(nèi)存釋放問題
本帖最后由 tianhailong 于 2015-09-30 19:25 編輯

今天遇到一個比較奇怪的問題,沒搞明白,請教一下:
下邊的程序 在構(gòu)造函數(shù)中申請了堆內(nèi)存,析構(gòu)時釋放,
執(zhí)行了2次構(gòu)造函數(shù),3次析構(gòu)函數(shù),就會出現(xiàn)對一塊內(nèi)存兩次釋放,
可是程序還能正常執(zhí)行,也不會coredump,不知道為什么呢?

#include <iostream>
using namespace std;

class Complex
{
public:
  float realPart;
  float virtualPart;
  char *p;
    Complex (float r, float v)
  {
    realPart = r;
    virtualPart = v;
    p = (char *) malloc (10);
    printf ("Construct %p\n", p);
  }
   ~Complex ()
  {
    free (p);
    printf ("Destruct %p\n", p);
  }
};


Complex
operator - (Complex c)
{
  return Complex (-c.realPart, -c.virtualPart);
}

int
main ()
{
  Complex c1 (11.1f, 22.2f);
  c1 = -c1;
  return 0;
}

執(zhí)行結(jié)果如下:

Construct 0x502010
Construct 0x502030
Destruct 0x502030
Destruct 0x502010
Destruct 0x502030

可以看到,對 0x502030 做了兩次釋放,我覺得應(yīng)該會coredump
但是卻沒有
作者: fender0107401    時間: 2015-09-30 19:57
執(zhí)行了不止2次的構(gòu)造函數(shù)吧。

你看到2次,是因?yàn)榫幾g器給你構(gòu)造的那個copy constructor里面沒有print語句。
作者: 何必抱怨    時間: 2015-10-08 10:49
本帖最后由 何必抱怨 于 2015-10-08 10:51 編輯

事實(shí)上是malloc了一次,然后卻free了兩次。

在vs2008下我試了下,debug模式下是會報錯的。
在g++ 4.6.3下試了一下,不會報錯

事實(shí)上lz的問題等價于:
  1.         char *p1 = (char *) malloc (10);
  2.         char *p2 = (char *) malloc (10);
  3.         free(p1);
  4.         free(p2);
  5.         free(p1);
復(fù)制代碼
為什么不會報錯。

我嘗試了一下,如果把上面的代碼改為:
  1.         char *p1 = (char *) malloc (10);
  2.         char *p2 = (char *) malloc (10);
  3.         free(p1);
  4.         free(p1);
復(fù)制代碼
在vs和g++下都會報錯的。
中間插入了free(p2);之后,vs下會報錯,g++下不會報錯,這個暫時不知道什么原因。

作者: lxyscls    時間: 2015-10-08 11:12
回復(fù) 1# tianhailong


    "undefined behavior" 又不代表一定會coredump

free.JPG (45.13 KB, 下載次數(shù): 50)

free.JPG

作者: lxyscls    時間: 2015-10-08 12:28
本帖最后由 lxyscls 于 2015-10-08 12:29 編輯

回復(fù) 3# 何必抱怨
  1. void
  2. public_fREe(void* mem)
  3. {
  4.   mstate ar_ptr;
  5.   mchunkptr p;                          /* chunk corresponding to mem */

  6.   void (*hook) (__malloc_ptr_t, __const __malloc_ptr_t)
  7.     = force_reg (__free_hook);
  8.   if (__builtin_expect (hook != NULL, 0)) {
  9.     (*hook)(mem, RETURN_ADDRESS (0));
  10.     return;
  11.   }

  12.   if (mem == 0)                              /* free(0) has no effect */
  13.     return;

  14.   p = mem2chunk(mem);

  15.   ... ...

  16.   ar_ptr = arena_for_chunk(p);
  17.   _int_free(ar_ptr, p, 0);
  18. }
復(fù)制代碼
對于較小的內(nèi)存分配,都在chunk里面分配,使用_init_free()。
  1. static void
  2. _int_free(mstate av, mchunkptr p, int have_lock)
  3. {
  4.   INTERNAL_SIZE_T size;        /* its size */
  5.   mfastbinptr*    fb;          /* associated fastbin */
  6.   mchunkptr       nextchunk;   /* next contiguous chunk */
  7.   INTERNAL_SIZE_T nextsize;    /* its size */
  8.   int             nextinuse;   /* true if nextchunk is used */
  9.   INTERNAL_SIZE_T prevsize;    /* size of previous contiguous chunk */
  10.   mchunkptr       bck;         /* misc temp for linking */
  11.   mchunkptr       fwd;         /* misc temp for linking */

  12.   const char *errstr = NULL;
  13.   int locked = 0;

  14.   size = chunksize(p);

  15.   ... ...

  16.   /*
  17.     If eligible, place chunk on a fastbin so it can be found
  18.     and used quickly in malloc.
  19.   */

  20.   if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())

  21.     ... ...

  22.     set_fastchunks(av);
  23.     unsigned int idx = fastbin_index(size);
  24.     fb = &fastbin (av, idx);

  25.     mchunkptr fd;
  26.     mchunkptr old = *fb;
  27.     unsigned int old_idx = ~0u;
  28.     do
  29.       {
  30.         /* Another simple check: make sure the top of the bin is not the
  31.            record we are going to add (i.e., double free).  */
  32.         if (__builtin_expect (old == p, 0))
  33.           {
  34.             errstr = "double free or corruption (fasttop)";
  35.             goto errout;
  36.           }
復(fù)制代碼
為什么free(p1);free(p1);會"double free",沒有細(xì)看代碼,我個人的理解是:兩次取得的chunk_size一樣,所以它認(rèn)為是"double free"。
為什么中間加了一個free(p2),就不會"double free"了,是因?yàn)樵賔ree(p1)的時候,chunk_size變了

因?yàn)閜1,p2的大小都是10,所以它們都在fastbin里面分配;如果把p2設(shè)置成一個比較大的值,比如13B,free(p1);free(p2);free(p1);一樣會"double free",因?yàn)閜2分配的chunk和p1不一樣,不影響第二次free(p1)時候的判斷





作者: YEETA    時間: 2015-10-09 17:50
樓上已經(jīng)回答你的問題了

我只提一下,
你的Complex對象在調(diào)用operator-傳遞參數(shù)的時候有拷貝構(gòu)造,此外還有(編譯器自動生成的)operator=的調(diào)用,這兩處都是bit-wise的拷貝
如果你的class要管理內(nèi)存,最好實(shí)現(xiàn)所有的copy ctor 和 operator=,否則很容易踩地雷(比如double free)
此外,用引用的方式傳遞函數(shù)參數(shù),避免不必要的構(gòu)造和析構(gòu)
作者: tianhailong    時間: 2015-10-10 20:46
那段代碼里邊是沒有拷貝構(gòu)造函數(shù)的,只有賦值回復(fù) 6# YEETA


   
作者: 何必抱怨    時間: 2015-10-12 09:07
回復(fù) 7# tianhailong
編譯器自動生成的。


   




歡迎光臨 Chinaunix (http://72891.cn/) Powered by Discuz! X3.2