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

Chinaunix

標(biāo)題: 線程創(chuàng)建子線程,線程退出時,釋放了內(nèi)存,但是TOP中只看到有一般的內(nèi)存被釋放了 [打印本頁]

作者: korpus    時間: 2014-02-12 14:40
標(biāo)題: 線程創(chuàng)建子線程,線程退出時,釋放了內(nèi)存,但是TOP中只看到有一般的內(nèi)存被釋放了

架構(gòu)是這樣的。

主進(jìn)程先初始化了一個線程池A,當(dāng)其中一個線程接收到任務(wù)的時候,就會去創(chuàng)建幾個子線程B來處理任務(wù)。(該A1線程使用pthread_jion等待子線程B退出,子線程用pthread_exit退出)。在子線程B中,使用了malloc函數(shù)連續(xù)分配了2段內(nèi)存。任務(wù)處理完后,在退出pthread_exit前,釋放他們。

其中的異,F(xiàn)象是這樣的,如果我在子線程B中加了日志打印的函數(shù),那么所有子線程退出時,上面申請的兩個連續(xù)內(nèi)存有一半的大小在top中顯示為未釋放(實(shí)際上,已經(jīng)釋放了,我向那2段內(nèi)存中memcpy程序core了)。如果我在子線程B中不加日志打印函數(shù),就不會有這個現(xiàn)象。

日志打印函數(shù),檢查過,沒有什么問題。

  1. #define LOG_INFO        Log_SysInfo(LOG_LEVEL_INFO,__FILE__,__LINE__),Log_Msg

  2. void Log_SysInfo(const int iLogLevel, const char *pszFileName, const int iNum)
  3. {
  4.     int i = 0;
  5.     char szLogTime[30];

  6.     //  加一個寫日志的線程鎖
  7.     pthread_mutex_lock(&g_WriteLog);

  8.     memset(szLogTime, 0, sizeof(szLogTime));
  9.     memset(g_szLogHead, 0, sizeof(g_szLogHead));

  10.     g_iLogLevel = iLogLevel;

  11.     //  如果設(shè)置的日志級別小直接返回
  12.     if(g_iSetLogLevel < g_iLogLevel)
  13.     {
  14.         return;
  15.     }

  16.     Log_Check();

  17.     timev_GetLogTime(szLogTime);
  18.     snprintf(g_szLogHead, sizeof(g_szLogHead), "%s %s L=%d T=%ld E=%d ", szLogTime, pszFileName,
  19.                  iNum, pthread_self(), errno);

  20.     switch(iLogLevel)
  21.     {
  22.         case LOG_LEVEL_ERROR:
  23.              sprintf(g_szLogHead + strlen(g_szLogHead), "%s", "[ERROR] ");
  24.              break;
  25.         case LOG_LEVEL_WARN:
  26.              sprintf(g_szLogHead + strlen(g_szLogHead), "%s", "[WARN] ");
  27.              break;
  28.         case LOG_LEVEL_DEBUG:
  29.              sprintf(g_szLogHead + strlen(g_szLogHead), "%s", "[DEBUG] ");
  30.              break;
  31.         case LOG_LEVEL_INFO:
  32.              sprintf(g_szLogHead + strlen(g_szLogHead), "%s", "[INFO] ");
  33.              break;
  34.         case LOG_LEVEL_ALL:
  35.              sprintf(g_szLogHead + strlen(g_szLogHead), "%s", "[ALL] ");
  36.              break;
  37.         default:
  38.              break;
  39.     }
  40. }

  41. void Log_Msg(const char *format, ...)
  42. {
  43.     FILE *fp;
  44.     va_list args;
  45.     int  olderrno;
  46.     //char szContext[1024*10];    //  分配10K的臨時變量空間,如果用內(nèi)存分配會不會影響性能
  47.     int i;

  48.     //  如果設(shè)置的日志級別小,則直接返回
  49.     if(g_iSetLogLevel < g_iLogLevel)
  50.     {
  51.         pthread_mutex_unlock(&g_WriteLog);
  52.         return;
  53.     }
  54.     olderrno = errno;     
  55.     //memset(szContext, 0, sizeof(szContext));

  56.     if(NULL != (fp = fopen(g_szLogFile, "a+")))
  57.     {
  58.         fprintf(fp, "%s", g_szLogHead);
  59.         va_start(args, format);
  60. //        fprintf(fp, "%s\n", szContext);
  61.         vfprintf(fp, format, args);
  62. //        fflush(fp);
  63.         va_end(args);
  64.         fprintf(fp, "%s", "\n");
  65.         fclose(fp);
  66.     }
  67.     else
  68.     {
  69.         printf("fopen error, errno=%d, file=%s\n", errno, g_szLogFile);
  70.         perror("fopen");
  71.         //printf("context1 [%s], file[%s:%d] \n", szContext, __FILE__, __LINE__);
  72.     }
  73.     errno = olderrno;

  74.     pthread_mutex_unlock(&g_WriteLog);
  75. }
復(fù)制代碼

作者: korpus    時間: 2014-02-12 14:45
這個是子線程的代碼,就算是這樣,先連續(xù)申請兩段內(nèi)存,然后釋放,top中顯示就沒有釋放完。  如果我在pReadMemory申請后,再釋放,pWriteMemory申請后,再釋放就是正常的。搞不懂是什么意思,求大哥大姐幫幫忙!
  1. void *trans_SingleThread(void *pData)
  2. {
  3.     int iRet;
  4.     MultTransData *pMultTransData = (MultTransData *)pData;
  5.     MMapData *pMMapData = NULL;
  6.     ListNode *pTemp = NULL;
  7.     void *pReadMemory = NULL;
  8.     void *pWriteMemory = NULL;
  9.     MMapData *pFirstSection = NULL;

  10.     pTemp = pMultTransData->m_pMMapDataList;
  11.     pFirstSection = (MMapData *)pTemp->pData;


  12.     //  為寫空間分配內(nèi)存地址
  13.     pWriteMemory = ufs_MallocMemory(pFirstSection->m_lWriteTotalSize);
  14.     if(NULL == pWriteMemory)
  15.     {
  16.         LOG_ERROR("Malloc Memory Failure!");
  17.         ufs_vFreeNormalMemory(&pReadMemory);
  18.         iRet = RT_FAILURE;
  19.         pthread_exit((void *)&iRet);
  20.     }

  21.     //  為讀空間分配內(nèi)存地址
  22.     pReadMemory = ufs_MallocMemory(pFirstSection->m_lReadTotalSize);
  23.     if(NULL == pReadMemory)
  24.     {
  25.         LOG_ERROR("Malloc Memory Failure!");
  26.         iRet = RT_FAILURE;
  27.         pthread_exit((void *)&iRet);
  28.     }


  29. LOG_DEBUG("Thread Will Quit");

  30. ufs_vFreeNormalMemory(&pReadMemory);
  31. ufs_vFreeNormalMemory(&pWriteMemory);



  32. pthread_exit((void *)&iRet);

  33. }
復(fù)制代碼

作者: korpus    時間: 2014-02-12 16:11
求幫助!有沒有哪個可以幫忙看看呢
作者: gaojl0728    時間: 2014-02-12 16:43
本帖最后由 gaojl0728 于 2014-02-12 16:45 編輯

回復(fù) 3# korpus


    1. 能不能把LOG_DEBUG的代碼貼出來。
2. 你是看top的哪一個字段?
3. 你說“我向那2段內(nèi)存中memcpy程序core了”, 什么叫core了, 是crash了嗎?
4. crash了, 不一定能證明就是釋放了, 把memcpy的代碼貼出來
作者: korpus    時間: 2014-02-12 16:56
回復(fù) 4# gaojl0728


    你好,謝謝你的關(guān)注,
1 LOG_DEBUG,貼出來了 ,就在第一個代碼里面的
2 top的res字段
3 意思好像沒有表達(dá)清楚,意思是,在我free那2段內(nèi)存后,為了檢查是否真的釋放了,然后向釋放的內(nèi)存memcpy內(nèi)容,然后程序crash了
4 memcpy(pReadMemory, "12345", 5);
作者: gaojl0728    時間: 2014-02-12 17:10
1. 你第一行貼的是LOG_INFO, 我想看看LOG_DEBUG。
2. ufs_vFreeNormalMemory傳遞的為什么是雙重指針,難道會把參數(shù)設(shè)置為NULL?
如果是寫NULL的話,你就不需要memcpy測試了, 直接看看是不是NULL就行了
3. 能不能把ufs_MallocMemory和ufs_vFreeNormalMemory的代碼貼出來看看?
如果實(shí)現(xiàn)是用的malloc和free, 那內(nèi)存可能被glibc的內(nèi)存池回收了,并沒有還給內(nèi)核。把代碼貼出來看看吧
4. pFirstSection->m_lWriteTotalSize和pFirstSection->m_lReadTotalSize的大小多少?

作者: gaojl0728    時間: 2014-02-12 17:11
回復(fù) 5# korpus


    1. 你第一行貼的是LOG_INFO, 我想看看LOG_DEBUG。
2. ufs_vFreeNormalMemory傳遞的為什么是雙重指針,難道會把參數(shù)設(shè)置為NULL?
如果是寫NULL的話,你就不需要memcpy測試了, 直接看看是不是NULL就行了
3. 能不能把ufs_MallocMemory和ufs_vFreeNormalMemory的代碼貼出來看看?
如果實(shí)現(xiàn)是用的malloc和free, 那內(nèi)存可能被glibc的內(nèi)存池回收了,并沒有還給內(nèi)核。把代碼貼出來看看吧
4. pFirstSection->m_lWriteTotalSize和pFirstSection->m_lReadTotalSize的大小多少?
作者: korpus    時間: 2014-02-12 17:37
回復(fù) 7# gaojl0728


    你好,首先謝謝您哈。
1. 你第一行貼的是LOG_INFO, 我想看看LOG_DEBUG。
  1. #define LOG_ERROR        Log_SysInfo(LOG_LEVEL_ERROR,__FILE__,__LINE__),Log_Msg
  2. #define LOG_WARN        Log_SysInfo(LOG_LEVEL_WARN,__FILE__,__LINE__),Log_Msg
  3. #define LOG_INFO        Log_SysInfo(LOG_LEVEL_INFO,__FILE__,__LINE__),Log_Msg
  4. #define LOG_DEBUG        Log_SysInfo(LOG_LEVEL_DEBUG,__FILE__,__LINE__),Log_Msg
復(fù)制代碼
2. ufs_vFreeNormalMemory傳遞的為什么是雙重指針,難道會把參數(shù)設(shè)置為NULL?
如果是寫NULL的話,你就不需要memcpy測試了, 直接看看是不是NULL就行了


是的,就是為了將其置為空,打印過,釋放后,確實(shí)也是NULL

3.函數(shù)如下
  1. void *ufs_MallocMemory(const long lSize)
  2. {
  3.     void *pAddr = NULL;
  4.     if(lSize <= 0)
  5.     {
  6.         LOG_ERROR("malloc memory size less than zero");
  7.         return NULL;
  8.     }

  9.     pAddr = malloc(lSize);
  10.     if(NULL == pAddr)
  11.     {
  12.         LOG_ERROR("malloc memory size error!, malloc size(%d)", lSize);
  13.         return NULL;
  14.     }

  15.     memset(pAddr, 0, lSize);

  16.     return pAddr;
  17. }

  18. void ufs_vFreeNormalMemory(void **pAddr)
  19. {
  20. //    LOG_WARN("TEST MEMORY FREE[%p]", *pAddr);

  21.     if(NULL == *pAddr)
  22.         return;
  23.     else
  24.         free(*pAddr);
  25.     *pAddr = NULL;
  26. }
復(fù)制代碼
是用的malloc與free,在網(wǎng)上也查了說有可能被glibc回收,但是每次我運(yùn)行一次的時候,內(nèi)存就增加了。

4. pFirstSection->m_lWriteTotalSize和pFirstSection->m_lReadTotalSize的大小多少?
這幾個值是設(shè)定的值,一般在10M以上

再次謝謝哈
作者: folklore    時間: 2014-02-12 17:59
內(nèi)存的問題我不猜~~



>>但是每次我運(yùn)行一次的時候,內(nèi)存就增加了。

如果是指進(jìn)程已經(jīng)結(jié)束重跑的話。
就不用擔(dān)心內(nèi)存問題了。
進(jìn)程一結(jié)束,
滲漏的內(nèi)存也會被OS自動回收。
作者: gaojl0728    時間: 2014-02-12 18:17
本帖最后由 gaojl0728 于 2014-02-12 18:22 編輯

回復(fù) 8# korpus

glibc只是一個可疑的點(diǎn),但是不確定是不是真的被內(nèi)存池回收而沒換給內(nèi)核了。
看你的代碼沒什么問題, 沒有內(nèi)存泄露, 也沒看到死鎖
如果不是被內(nèi)存池緩存的話,我感覺可能只是一個top的顯示問題
作者: 一只嗡嗡的蒼蠅    時間: 2014-02-12 22:36
gcc和操作系統(tǒng)均有可能有內(nèi)存池。
作者: korpus    時間: 2014-02-13 08:53
回復(fù) 10# gaojl0728


    就是最奇怪的就是,如果我把LOG_DEBUG("Thread Will Quit");  這行注釋掉,top命令顯示就是正常的。

作者: korpus    時間: 2014-02-13 08:55
回復(fù) 9# folklore


    你好,謝謝的你的關(guān)注哈。

進(jìn)程結(jié)束,內(nèi)存是會被回收的,現(xiàn)在是在線程里面。
作者: korpus    時間: 2014-02-13 09:03
回復(fù) 11# 一只嗡嗡的蒼蠅


    你好,謝謝你的關(guān)注。
能不能確認(rèn)這個內(nèi)存池呢
作者: folklore    時間: 2014-02-13 09:55
上 Valgrind 吧。
作者: korpus    時間: 2014-02-13 16:18
本帖最后由 korpus 于 2014-02-13 16:23 編輯

我把代碼整理出來了一份可以獨(dú)立編譯  

比較奇怪的是如果注釋掉函數(shù) trans_SingleThread  LOG_DEBUG("Thread Will Quit [%ld]", pthread_self());,釋放回正常,如果沒注釋釋放就不正常了
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #include <stdarg.h>
  7. #include <sys/timeb.h>
  8. #include <sys/stat.h>
  9. #include <pthread.h>

  10. typedef enum
  11. {
  12.     LOG_LEVEL_ERROR, // only print ERROR log
  13.     LOG_LEVEL_WARN,  // print ERROR and WARN log
  14.     LOG_LEVEL_INFO,  // print ERROR, WARN and INFO log
  15.     LOG_LEVEL_DEBUG,  // print ERROR, WARN, INFO AND DEBUG log
  16.     LOG_LEVEL_ALL    // print all log, and print full debug log and other informations
  17. }LOG_LEVEL;

  18. static char g_szLogHead[200];
  19. static long g_iSetLogLevel = 3;
  20. static long g_lSetLogSize = 0;
  21. static int g_iLogLevel;
  22. static char g_szLogFile[256]="./test.log";
  23. pthread_mutex_t g_WriteLog = PTHREAD_MUTEX_INITIALIZER;
  24. static char g_szLogPath[128]=".";
  25. static char g_szLogName[128]="test.log";

  26. #define LOG_ERROR       Log_SysInfo(LOG_LEVEL_ERROR,__FILE__,__LINE__),Log_Msg
  27. #define LOG_WARN        Log_SysInfo(LOG_LEVEL_WARN,__FILE__,__LINE__),Log_Msg
  28. #define LOG_INFO        Log_SysInfo(LOG_LEVEL_INFO,__FILE__,__LINE__),Log_Msg
  29. #define LOG_DEBUG       Log_SysInfo(LOG_LEVEL_DEBUG,__FILE__,__LINE__),Log_Msg
  30. #define RT_SUCCESS      0
  31. #define RT_FAILURE      -1

  32. void Log_Check();

  33. long timel_GetCurrentTime()
  34. {
  35.     char szTime[7];
  36.     long lCurTime;
  37.     struct tm *ptime;
  38.     time_t times;
  39.     time(&times);
  40.     ptime = localtime(&times);
  41.     memset(szTime, 0, sizeof(szTime));
  42.     sprintf(szTime, "%02d%02d%02d", ptime->tm_hour, ptime->tm_min, ptime->tm_sec);
  43.     lCurTime = atol(szTime);
  44.     return lCurTime;
  45. }

  46. long timel_GetCurrentDate()
  47. {
  48.     char szDate[9];
  49.     long lDate;
  50.     struct tm *ptm;
  51.     time_t times;
  52.     time(&times);
  53.     ptm = localtime(&times);
  54.     memset(szDate, 0, sizeof(szDate));
  55.     sprintf(szDate, "%d%02d%02d", ptm->tm_year+1900, ptm->tm_mon + 1, ptm->tm_mday);
  56.     lDate = atol(szDate);
  57.     return lDate;
  58. }

  59. void timev_GetLogTime(char *out_pLogTime)
  60. {
  61.     struct timeb ptm;
  62.     struct tm *ptmb;

  63.     ftime(&ptm);
  64.     ptmb = localtime(&ptm.time);
  65.     sprintf(out_pLogTime, "%02d-%02d %02d:%02d:%02d.%03d", ptmb->tm_mon+1, ptmb->tm_mday,
  66.                        ptmb->tm_hour, ptmb->tm_min, ptmb->tm_sec, ptm.millitm);
  67.     return ;
  68. }

  69. void Log_SysInfo(const int iLogLevel, const char *pszFileName, const int iNum)
  70. {
  71.     int i = 0;
  72.     char szLogTime[30];

  73.     pthread_mutex_lock(&g_WriteLog);

  74.     memset(szLogTime, 0, sizeof(szLogTime));
  75.     memset(g_szLogHead, 0, sizeof(g_szLogHead));

  76.     g_iLogLevel = iLogLevel;

  77.     if(g_iSetLogLevel < g_iLogLevel)
  78.     {
  79.         return;
  80.     }

  81.     Log_Check();

  82.     timev_GetLogTime(szLogTime);
  83.     snprintf(g_szLogHead, sizeof(g_szLogHead), "%s %s L=%d T=%ld E=%d ", szLogTime, pszFileName,
  84.                  iNum, pthread_self(), errno);

  85.     switch(iLogLevel)
  86.     {
  87.         case LOG_LEVEL_ERROR:
  88.              sprintf(g_szLogHead + strlen(g_szLogHead), "%s", "[ERROR] ");
  89.              break;
  90.         case LOG_LEVEL_WARN:
  91.              sprintf(g_szLogHead + strlen(g_szLogHead), "%s", "[WARN] ");
  92.              break;
  93.         case LOG_LEVEL_DEBUG:
  94.              sprintf(g_szLogHead + strlen(g_szLogHead), "%s", "[DEBUG] ");
  95.              break;
  96.         case LOG_LEVEL_INFO:
  97.              sprintf(g_szLogHead + strlen(g_szLogHead), "%s", "[INFO] ");
  98.              break;
  99.         case LOG_LEVEL_ALL:
  100.              sprintf(g_szLogHead + strlen(g_szLogHead), "%s", "[ALL] ");
  101.              break;
  102.         default:
  103.              break;
  104.     }
  105. }

  106. void Log_Check()
  107. {
  108.     struct stat st;
  109.     int iRet;
  110.     char szLogDate[9];

  111.     memset(szLogDate, 0, sizeof(szLogDate));
  112.     memcpy(szLogDate, g_szLogFile + strlen(g_szLogPath) + 1, 8);

  113.     if(atol(szLogDate) == timel_GetCurrentDate())
  114.     {
  115.         if(g_lSetLogSize > 0)
  116.         {
  117.             stat(g_szLogFile, &st);
  118.             if(st.st_size / 1024 / 1024 >= g_lSetLogSize)
  119.             {
  120.                 snprintf(g_szLogFile, sizeof(g_szLogFile), "%s/%ld/%s.%ld%s%06d", g_szLogPath,
  121.                         timel_GetCurrentDate(), g_szLogName,
  122.                         timel_GetCurrentDate(), "_", timel_GetCurrentTime());
  123.             }
  124.             
  125.         }
  126.     }
  127.     else
  128.     {  
  129.         if(g_lSetLogSize > 0)
  130.         {
  131.             snprintf(g_szLogFile, sizeof(g_szLogFile), "%s/%ld/%s.%ld%s%06d", g_szLogPath,
  132.                     timel_GetCurrentDate(), g_szLogName,
  133.                     timel_GetCurrentDate(), "_", timel_GetCurrentTime());

  134.         }
  135.         else
  136.         {
  137.             snprintf(g_szLogFile, sizeof(g_szLogFile), "%s/%ld/%s.%ld", g_szLogPath,
  138.                         timel_GetCurrentDate(), g_szLogName,
  139.                         timel_GetCurrentDate());
  140.         }
  141.     }
  142. }

  143. void Log_Msg(const char *format, ...)
  144. {
  145.     FILE *fp;
  146.     va_list args;
  147.     int  olderrno;
  148.     int i;

  149.     if(g_iSetLogLevel < g_iLogLevel)
  150.     {
  151.         pthread_mutex_unlock(&g_WriteLog);
  152.         return;
  153.     }
  154.     olderrno = errno;     

  155.     if(NULL != (fp = fopen(g_szLogFile, "a+")))
  156.     {
  157.         fprintf(fp, "%s", g_szLogHead);
  158.         va_start(args, format);
  159.         vfprintf(fp, format, args);
  160.         va_end(args);
  161.         fprintf(fp, "%s", "\n");
  162.         fclose(fp);
  163.     }
  164.     else
  165.     {
  166.         printf("fopen error, errno=%d, file=%s\n", errno, g_szLogFile);
  167.         perror("fopen");
  168.     }
  169.     errno = olderrno;

  170.     pthread_mutex_unlock(&g_WriteLog);
  171. }

  172. void *ufs_MallocMemory(const long lSize)
  173. {
  174.     void *pAddr = NULL;
  175.     if(lSize <= 0)
  176.     {
  177.         LOG_ERROR("malloc memory size less than zero");
  178.         return NULL;
  179.     }

  180.     pAddr = malloc(lSize);
  181.     if(NULL == pAddr)
  182.     {
  183.         LOG_ERROR("malloc memory size error!, malloc size(%d)", lSize);
  184.         return NULL;
  185.     }

  186.     memset(pAddr, 0, lSize);

  187.     return pAddr;
  188. }

  189. void ufs_vFreeNormalMemory(void **pAddr)
  190. {
  191.     if(NULL == *pAddr)
  192.         return;
  193.     else
  194.         free(*pAddr);
  195.     *pAddr = NULL;
  196. }

  197. void *trans_SingleThread(void *pData)
  198. {
  199.     int iRet;
  200.     void *pReadMemory = NULL;
  201.     void *pWriteMemory = NULL;

  202.     pWriteMemory = ufs_MallocMemory(20971520);
  203.     if(NULL == pWriteMemory)
  204.     {
  205.         LOG_ERROR("Malloc Memory Failure!");
  206.         ufs_vFreeNormalMemory(&pReadMemory);
  207.         iRet = RT_FAILURE;
  208.         pthread_exit((void *)&iRet);
  209.     }

  210.     pReadMemory = ufs_MallocMemory(20971520);
  211.     if(NULL == pReadMemory)
  212.     {
  213.         LOG_ERROR("Malloc Memory Failure!");
  214.         iRet = RT_FAILURE;
  215.         pthread_exit((void *)&iRet);
  216.     }

  217.     sleep(5);

  218.     LOG_DEBUG("Thread Will Quit [%ld]", pthread_self());

  219.     ufs_vFreeNormalMemory(&pReadMemory);
  220.     ufs_vFreeNormalMemory(&pWriteMemory);


  221.     pthread_exit((void *)&iRet);
  222. }

  223. void *pFunc(void *pData)
  224. {
  225.     int *iTime = (int *)pData;
  226.     long lThreadID[10];
  227.     int i;

  228.     *iTime = 5;
  229.     while(1)
  230.     {
  231.         for(i = 0; i < *iTime; i ++)
  232.         {
  233.             if(pthread_create(&lThreadID[i], NULL, trans_SingleThread, NULL) < 0)
  234.             {
  235.                 printf("create error\n");
  236.                 exit(0);
  237.             }
  238.       

  239.             LOG_DEBUG("Success Create Thread [%ld]", lThreadID[i]);
  240.         }

  241.         for(i = 0; i < *iTime; i ++)
  242.         {
  243.             pthread_join(lThreadID[i], NULL);
  244.             LOG_DEBUG("Thread [%ld] Quit Success!", lThreadID[i]);
  245.         }

  246.         sleep(*iTime * 5);
  247.     }
  248. }

  249. int main(int argc, char *argv[])
  250. {
  251.     long lThreadID[10];
  252.     int i;
  253.     int iRet;
  254.     int iThreadNums;

  255.     iThreadNums = atoi(argv[1]);

  256.     if(iThreadNums > 10 || argc != 2)
  257.     {
  258.         printf("less than 10, or input 2 args!\n");
  259.         exit(0);
  260.     }

  261.     sleep(5);

  262.     for(i = 0; i < iThreadNums; i ++)
  263.     {
  264.         iRet = pthread_create(&lThreadID[i], NULL, pFunc, &iThreadNums);
  265.         if(iRet < 0)
  266.         {
  267.             printf("error ,exit!\n");
  268.             exit(0);
  269.         }

  270.         LOG_DEBUG("Create Initinal Thread [%ld]", lThreadID[i]);
  271.     }

  272.     while(1)
  273.     {
  274.         sleep(2);
  275.     }
  276. }
復(fù)制代碼
makefile如下
  1. all:TestMemory

  2. TestMemory:thread.o
  3.         cc -o TestMemory thread.o -lpthread
  4.         rm -f thread.o
  5. thread.c:thread.o
  6.         cc -c thread.c
復(fù)制代碼

作者: gaojl0728    時間: 2014-02-13 18:38
回復(fù) 16# korpus


    抓了個strace看了下, LOG_DEBUG存在的時候Glibc沒有釋放那20M內(nèi)存給內(nèi)核。 要想知道詳細(xì)的原因只能看glibc了, 可惜glibc代碼的可讀性太差, 不好看啊
作者: korpus    時間: 2014-02-14 10:02
回復(fù) 17# gaojl0728


    你好,你用strace怎么看的呢?

    如果glibc沒有返回給系統(tǒng),正常嗎?
作者: gaojl0728    時間: 2014-02-14 10:42
回復(fù) 18# korpus


   
strace -f -p "pid of your program"能看到程序調(diào)用的系統(tǒng)調(diào)用, 對于大于128K的內(nèi)存分配, glibc會調(diào)用mmap/munmap/madvise分配釋放內(nèi)存,

你的程序分別分配了兩塊20M的內(nèi)存,然后分別釋放掉:
1. 沒有LOG_DEBUG的時候,  一塊20M內(nèi)存是通過munmap釋放掉的,另一塊20M是madvise釋放掉的。
2. 有LOG_DEBUG的時候, 一塊20M內(nèi)存是通過munmap釋放掉的, 另一塊沒有釋放被glibc 回收緩存了。

通常內(nèi)存池會回收并緩存釋放的內(nèi)存而不歸還給內(nèi)核,這是正常的行為,不是內(nèi)存泄露。
要想知道原因只能看glibc的源代碼, 可能pthread的相關(guān)函數(shù)做了某些特殊處理。
作者: korpus    時間: 2014-02-14 11:35
回復(fù) 19# gaojl0728


    謝謝你哈。我看看。
作者: korpus    時間: 2014-02-14 15:25
回復(fù) 19# gaojl0728


    1、你好,你是怎么看到的mmap分配的20M內(nèi)存,munmap\madvise釋放的呢,我感覺我strace -f -p看到的只是主線程的,沒有看到創(chuàng)建的子線程分配情況。
    2、這個內(nèi)存如果一直增長,到底正常不呢,會不會影響性能?
   




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