青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

我們的工程馬上就要發布,但是在一個干凈的,即沒有安裝vs2005的xp上運行(利用虛擬機測試)卻彈出下面得錯誤
“由于應用程序配置不正確,應用程序未能啟動。重新安裝應用程序可能會糾正這個問題“
在英文os上:
This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.
考慮到程序的運行環境問題,可能是由于沒有安裝.netFrameWork.但是后來安裝上之后仍然如故。郁悶。。。
在網上找出了這些方法:
方法一:
在類似C:\Program Files\Microsoft Visual Studio 8\VC\redi
st\Debug_NonRedist\x86\Microsoft.VC80.DebugCRT 下找到了下列文件:
msvcm80d.dll
msvcp80d.dll
msvcr80d.dll
Microsoft.VC80.DebugCRT.manifest
把這幾個文件拷貝到目標機器上,與運行程序同一文件夾或放到system32下,就可以正確運行了。
其他release版、MFC程序什么的都是拷redist下相應文件夾下的文件就可以了,文件夾后都有標識!
方法二:
修改編譯選項,將/MD或/MDd 改為 /MT或/MTd,這樣就實現了對VC運行時庫的靜態鏈接,在運行時就不再需要VC的dll了。
注:MSDN中對于在不同的配置下Link的LIB作了說明:
C Runtime Library:
開關 對應的庫 版本
/MD MSVCRT.LIB 多線程DLL的Release版本
/MDd MSVCRTD.LIB 多線程DLL的Debug版本
/MT LIBCMT.LIB 多線程靜態鏈接的Release版本
/MTd LIBCMTD.LIB 多線程靜態鏈接的Debug版本
/clr MSVCMRT.LIB 托管代碼和非托管代碼混合
/clr:pure MSVCURT.LIB 純托管代碼 
C++ Standard Library:
開關 對應的庫 版本
/MD MSVCPRT.LIB 多線程DLL的Release版本
/MDd MSVCPRTD.LIB 多線程DLL的Debug版本
/MT LIBCPMT.LIB 多線程靜態鏈接的Release版本
/MTd LIBCPMTD.LIB 多線程靜態鏈接的Debug版本 
編譯器會自動根據編譯選項,選擇對應的LIB文件。一般情況下這不會出現問題。
然而,在部分情況下,一旦你的程序的各個部分(LIB, OBJ…)并非由相同的編譯選項編譯出,而Link在一起的話,會出現各種各樣的看似很難解決的問題,這類問題主要以重復定義的錯誤形式存在,通常的解決方法也很簡單,就是選擇同樣的編譯選項進行編譯之后再Link
方法三:
工程-》屬性-》配置屬性-》常規-》MFC的使用,選擇“在靜態庫中使用mfc”
這樣生成的exe文件應該就可以在其他機器上跑了。
方法四:
安裝vcredist_x86.exe

這樣四步下來,大部分程序都應該可以運行了,但悲哀的是在我的測試機上還是報應用程序配置錯誤。無奈。。
后打開vs2005的命令行,運行depends.exe,試圖找出程序啟動所依賴的dll,結果大失所望,虛擬機上這些dll都有。如此這般令人抓狂。
最后把vs2005安裝目錄下的所有.manifest文件(可以搜索 *.manifest得到)都考到程序目錄下,程序奇跡般的可以運行。
然后實驗,刪掉冗余的.manifest文件,只需要5個就夠了。它們是Microsoft.VC80.ATL.manifest
Microsoft.VC80.CRT.manifest
Microsoft.VC80.DebugCRT.manifest
Microsoft.VC80.DebugMFC.manifest
Microsoft.VC80.MFC.manifest

posted @ 2009-11-10 13:58 micheal's tech 閱讀(893) | 評論 (0)編輯 收藏

方法1:過該點作一條射線,然后判斷該射線與三條邊的相交情況;  
  方法2:分別連接P點和三個頂點A,B,C,然后判斷矢量PA,PB,PC所夾角之和是否為360度,如果是360度則P在三角形內  
   
  1.    
  #include   <stdio.h>  
  #include   <math.h>  
   
  struct   TPoint  
  {  
  float   x;  
  float   y;  
  };  
   
  float   area(struct   TPoint   p1,struct   TPoint   p2,struct   TPoint   p3){  
  return   fabs((p1.x-p3.x)*(p2.y-p3.y)-(p2.x-p3.x)*(p1.y-p3.y));  
  }  
   
  float   mul(struct   TPoint   p1,struct   TPoint   p2,struct   TPoint   p0){  
  return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));  
  }  
   
  int   inside(struct   TPoint   tr[],struct   TPoint   p){  
  int   i;  
  for   (i=0;i<3;i++)  
  if   (mul(p,tr[i],tr[(i+1)%3])*mul(p,tr[(i+2)%3],tr[(i+1)%3])>0)  
  return   0;  
  return   1;  
  }  
   
  int   inside2(struct   TPoint   tr[],struct   TPoint   p){  
  if   (fabs(area(tr[0],tr[1],tr[2])-  
    area(p,tr[1],tr[2])-  
    area(tr[0],p,tr[2])-  
    area(tr[0],tr[1],p))<1.0e-20)  
  return   1;  
  else  
  return   0;  
  }  
   
  main(){  
  struct   TPoint   tr[3]={{-1,1},{1,0},{3,0}},p={1,2};  
  printf("algorithm   1:");  
  if   (inside(tr,p))  
  printf("In\n");  
  else  
  printf("Out\n");  
  printf("algorithm   2:");  
  if   (inside2(tr,p))  
  printf("In\n");  
  else  
  printf("Out\n");  
  }  
   
  2  
  就是判斷點到三個頂點的夾角之和為2*PI  
  //   返回1   表示在那,0表示在外  
  int   inside3(const   struct   TPoint   tr[],   struct   TPoint   p)  
  {  
  TPoint   p0,p1,p2;  
  p0.x   =   tr[0].x   -   p.x   ;     p0.y   =   tr[0].y   -   p.y;  
  p1.x   =   tr[1].x   -   p.x   ;     p1.y   =   tr[1].y   -   p.y;  
  p2.x   =   tr[2].x   -   p.x   ;     p2.y   =   tr[2].y   -   p.y;  
   
  double   arg1   =   acos((p0.x*p1.x   +   p0.y*p1.y)/sqrt(p0.x*p0.x   +   p0.y*p0.y)/sqrt(p1.x*p1.x+p1.y*p1.y));  
  double   arg2   =   acos((p0.x*p2.x   +   p0.y*p2.y)/sqrt(p0.x*p0.x   +   p0.y*p0.y)/sqrt(p2.x*p2.x+p2.y*p2.y));  
  double   arg3   =   acos((p2.x*p1.x   +   p2.y*p1.y)/sqrt(p2.x*p2.x   +   p2.y*p2.y)/sqrt(p1.x*p1.x+p1.y*p1.y));  
   
  if(   fabs(2*3.1415926-arg1-arg2-arg3)<0.0001   )   return   1;  
  return   0;  
  }  
   

posted @ 2009-11-04 21:07 micheal's tech 閱讀(1835) | 評論 (0)編輯 收藏

directhsow filter 里不能用std::vector


You've got a very odd mix of managed and unmanaged code.  You're definitely missing msvcprtd.lib.  That should knock a good chunk of those errors out.  Project templates are almost always a good idea.

posted @ 2009-11-04 16:18 micheal's tech 閱讀(195) | 評論 (0)編輯 收藏

    今天dot.kde登了一篇對valgrind的作者 訪談。我作為valgrind的老用戶,當年調程序時獲益很多,在這篇訪談里進一步長了見識,深感有必要把這個優秀的開發工具介紹給諸位。以下內容多翻譯自該訪談(意譯啦)。

啥是valgrind

    Valgrind是幫助程序員尋找程序里的bug和改進程序性能的工具。程序通過valgrind運行時,valgrind收集各種有用的信息,通過這些信息可以找到程序中潛在的bug和性能瓶頸。
    Valgrind現在提供多個工具,其中最重要的是Memcheck,Cachegrind,Massif和Callgrind。

Memcheck:

    這個工具可以用來尋找c、c++和fortran程序中內存管理的錯誤。寫c或c++程序時,很多隱藏很深的bug是內存操作上出了問題。而這些在 Memcheck面前都無處遁形(偶當年用的就是這個功能)。Memcheck可以檢查出下列幾種內存操作上的錯誤(大家自查一下有沒有犯過;):
  • 讀寫已經釋放的內存
  • 讀寫內存塊越界(從前或者從后)
  • 使用還未初始化的變量
  • 將無意義的參數傳遞給系統調用
  • 內存泄漏
  • (筆者補充一條,同一個malloc的內存塊釋放多次。當年這么個bug讓我找翻天)      

Cachegrind:

    這個工具可以提供詳盡的profiling信息。它不光對指令、內存訪問進行計數,更能針對每條指令、每行源代碼、每個函數和每個程序統計cache的不 命中次數。大家應該知道,cache對目前系統的性能有決定性的影響。因此這些信息可以指導程序員調整代碼,最大限度的提高程序性能。
    訪談中提到,valgrind自身利用該工具在過去幾個月內使性能提高了25%-30%。據早先報道,kde的開發team也對valgrind在提高kde性能方面的幫助表示感謝。

Massif:

    Massif對內存的分配和釋放做profile。程序開發者通過它可以深入了解程序的內存使用行為,從而對內存使用進行優化。這個功能對C++尤其有用(因為C++有很多隱藏的內存分配和釋放)。

Callgrind:

    Callgrind是一個復雜的工具(復雜到筆者沒看太明白有關它的介紹)。它基于Cachegrind,除了具有Cachegrind的功能外,還可以統計調用帶來的開銷。

用法:

    Valgrind使用起來非常簡單,你甚至不需要重新編譯你的程序就可以用它。當然如果要達到最好的效果,獲得最準確的信息,還是需要按要求重新編譯一下的。比如在使用memcheck的時候,最好關閉優化選項。

posted @ 2009-02-02 16:50 micheal's tech 閱讀(825) | 評論 (0)編輯 收藏

【轉】一個簡單的線程池(c++版)

#ifndef _ThreadPool_H_
#define _ThreadPool_H_
#pragma warning(disable: 4530)
#pragma warning(disable: 4786)
#include <cassert>
#include <vector>
#include <queue>
#include <windows.h>
class ThreadJob  //工作基類
{
public:
    //供線程池調用的虛函數
    virtual void DoJob(void *pPara) = 0;
};
class ThreadPool
{
public:
    //dwNum 線程池規模
    ThreadPool(DWORD dwNum = 4) : _lThreadNum(0), _lRunningNum(0)
    {
        InitializeCriticalSection(&_csThreadVector);
        InitializeCriticalSection(&_csWorkQueue);
        _EventComplete = CreateEvent(0, false, false, NULL);
        _EventEnd = CreateEvent(0, true, false, NULL);
        _SemaphoreCall = CreateSemaphore(0, 0,  0x7FFFFFFF, NULL);
        _SemaphoreDel =  CreateSemaphore(0, 0,  0x7FFFFFFF, NULL);
        assert(_SemaphoreCall != INVALID_HANDLE_VALUE);
        assert(_EventComplete != INVALID_HANDLE_VALUE);
        assert(_EventEnd != INVALID_HANDLE_VALUE);
        assert(_SemaphoreDel != INVALID_HANDLE_VALUE);
        AdjustSize(dwNum <= 0 ? 4 : dwNum);
    }
    ~ThreadPool()
    {
        DeleteCriticalSection(&_csWorkQueue);
        CloseHandle(_EventEnd);
        CloseHandle(_EventComplete);
        CloseHandle(_SemaphoreCall);
        CloseHandle(_SemaphoreDel);
        vector<ThreadItem*>::iterator iter;
        for(iter = _ThreadVector.begin(); iter != _ThreadVector.end(); iter++)
        {
            if(*iter)
                delete *iter;
        }
        DeleteCriticalSection(&_csThreadVector);
    }
    //調整線程池規模
    int AdjustSize(int iNum)
    {
        if(iNum > 0)
        {
            ThreadItem *pNew;
            EnterCriticalSection(&_csThreadVector);
            for(int _i=0; _i<iNum; _i++)
            {
                _ThreadVector.push_back(pNew = new ThreadItem(this));
                assert(pNew);
                pNew->_Handle = CreateThread(NULL, 0, DefaultJobProc, pNew, 0, NULL);
                assert(pNew->_Handle);
            }
            LeaveCriticalSection(&_csThreadVector);
        }
        else
        {
            iNum *= -1;
            ReleaseSemaphore(_SemaphoreDel,  iNum > _lThreadNum ? _lThreadNum : iNum, NULL);
        }
        return (int)_lThreadNum;
    }
    //調用線程池
    void Call(void (*pFunc)(void  *), void *pPara = NULL)
    {
        assert(pFunc);
        EnterCriticalSection(&_csWorkQueue);
        _JobQueue.push(new JobItem(pFunc, pPara));
        LeaveCriticalSection(&_csWorkQueue);
        ReleaseSemaphore(_SemaphoreCall, 1, NULL);
    }
    //調用線程池
    inline void Call(ThreadJob * p, void *pPara = NULL)
    {
        Call(CallProc, new CallProcPara(p, pPara));
    }
    //結束線程池, 并同步等待
    bool EndAndWait(DWORD dwWaitTime = INFINITE)
    {
        SetEvent(_EventEnd);
        return WaitForSingleObject(_EventComplete, dwWaitTime) == WAIT_OBJECT_0;
    }
    //結束線程池
    inline void End()
    {
        SetEvent(_EventEnd);
    }
    inline DWORD Size()
    {
        return (DWORD)_lThreadNum;
    }
    inline DWORD GetRunningSize()
    {
        return (DWORD)_lRunningNum;
    }
    bool IsRunning()
    {
        return _lRunningNum > 0;
    }
protected:
    //工作線程
    static DWORD WINAPI DefaultJobProc(LPVOID lpParameter = NULL)
    {
        ThreadItem *pThread = static_cast<ThreadItem*>(lpParameter);
        assert(pThread);
        ThreadPool *pThreadPoolObj = pThread->_pThis;
        assert(pThreadPoolObj);
        InterlockedIncrement(&pThreadPoolObj->_lThreadNum);
        HANDLE hWaitHandle[3];
        hWaitHandle[0] = pThreadPoolObj->_SemaphoreCall;
        hWaitHandle[1] = pThreadPoolObj->_SemaphoreDel;
        hWaitHandle[2] = pThreadPoolObj->_EventEnd;
        JobItem *pJob;
        bool fHasJob;
        for(;;)
        {
            DWORD wr = WaitForMultipleObjects(3, hWaitHandle, false, INFINITE);
            //響應刪除線程信號
            if(wr == WAIT_OBJECT_0 + 1) 
                break;
            //從隊列里取得用戶作業
            EnterCriticalSection(&pThreadPoolObj->_csWorkQueue);
            if(fHasJob = !pThreadPoolObj->_JobQueue.empty())
            {
                pJob = pThreadPoolObj->_JobQueue.front();
                pThreadPoolObj->_JobQueue.pop();
                assert(pJob);
            }
            LeaveCriticalSection(&pThreadPoolObj->_csWorkQueue);
            //受到結束線程信號確定是否結束線程(結束線程信號&& 是否還有工作)
            if(wr == WAIT_OBJECT_0 + 2 && !fHasJob) 
                break;
            if(fHasJob && pJob)
            {
                InterlockedIncrement(&pThreadPoolObj->_lRunningNum);
                pThread->_dwLastBeginTime = GetTickCount();
                pThread->_dwCount++;
                pThread->_fIsRunning = true;
                pJob->_pFunc(pJob->_pPara); //運行用戶作業
                delete pJob;
                pThread->_fIsRunning = false;
                InterlockedDecrement(&pThreadPoolObj->_lRunningNum);
            }
        }
        //刪除自身結構
        EnterCriticalSection(&pThreadPoolObj->_csThreadVector);
    pThreadPoolObj->_ThreadVector.erase(find(pThreadPoolObj->_ThreadVector.begin(), pThreadPoolObj->_ThreadVector.end(), pThread));
        LeaveCriticalSection(&pThreadPoolObj->_csThreadVector);
        delete pThread;
        InterlockedDecrement(&pThreadPoolObj->_lThreadNum);
        if(!pThreadPoolObj->_lThreadNum)  //所有線程結束
            SetEvent(pThreadPoolObj->_EventComplete);
        return 0;
    }
    //調用用戶對象虛函數
    static void CallProc(void *pPara)
    {
        CallProcPara *cp = static_cast<CallProcPara *>(pPara);
        assert(cp);
        if(cp)
        {
            cp->_pObj->DoJob(cp->_pPara);
            delete cp;
        }
    }
    //用戶對象結構
    struct CallProcPara 
    {
        ThreadJob* _pObj;//用戶對象
        void *_pPara;//用戶參數
        CallProcPara(ThreadJob* p, void *pPara) : _pObj(p), _pPara(pPara) { };
    };
    //用戶函數結構
    struct JobItem
    {
        void (*_pFunc)(void  *);//函數
        void *_pPara; //參數
        JobItem(void (*pFunc)(void  *) = NULL, void *pPara = NULL) : _pFunc(pFunc), _pPara(pPara) { };
    };
    //線程池中的線程結構
    struct ThreadItem
    {
        HANDLE _Handle; //線程句柄
        ThreadPool *_pThis;  //線程池的指針
        DWORD _dwLastBeginTime; //最后一次運行開始時間
        DWORD _dwCount; //運行次數
        bool _fIsRunning;
        ThreadItem(ThreadPool *pthis) : _pThis(pthis), _Handle(NULL), _dwLastBeginTime(0), _dwCount(0), _fIsRunning(false) { };
        ~ThreadItem()
        {
            if(_Handle)
            {
                CloseHandle(_Handle);
                _Handle = NULL;
            }
        }
    };
    std::queue<JobItem *> _JobQueue;  //工作隊列
    std::vector<ThreadItem *>  _ThreadVector; //線程數據
    CRITICAL_SECTION _csThreadVector, _csWorkQueue; //工作隊列臨界, 線程數據臨界
    HANDLE _EventEnd, _EventComplete, _SemaphoreCall, _SemaphoreDel;//結束通知, 完成事件, 工作信號,刪除線程信號
    long _lThreadNum, _lRunningNum; //線程數, 運行的線程數
};
#endif //_ThreadPool_H_

使用說明1:

調用方法

void threadfunc(void *p)
{
     YourClass* yourObject = (YourClass*)    p;
 //
}
 ThreadPool tp;
 for(i=0; i<100; i++)
  tp.Call(threadfunc);
ThreadPool tp(20);//20為初始線程池規模
 tp.Call(threadfunc, lpPara);

使用時注意幾點:

1. ThreadJob  沒什么用,直接寫線程函數吧。 

2. 線程函數(threadfunc)的入口參數void* 可以轉成自定義的類型對象,這個對象可以記錄下線程運行中的數據,并設置線程當前狀態,以此與線程進行交互。

3. 線程池有一個EndAndWait函數,用于讓線程池中所有計算正常結束。有時線程池中的一個線程可能要運行很長時間,怎么辦?可以通過線程函數threadfunc的入口參數對象來處理,比如:

class YourClass 
{
  int cmd; // cmd = 1是上線程停止計算,正常退出。
};
threadfunc(void* p) {
  YourClass* yourObject = (YourClass*)p;
  while (true) {
    // do some calculation
    if (yourClass->cmd == 1)
      break;
  }
}

在主線程中設置yourClass->cmd = 1,該線程就會自然結束。

使用說明2:

Code
void threadfunc(void *p)
{
 //
}
 ThreadPool tp;
 for(i=0; i<100; i++)
  tp.Call(threadfunc);
 ThreadPool tp(20);//20為初始線程池規模
 tp.Call(threadfunc, lpPara);
 tp.AdjustSize(50);//增加50
 tp.AdjustSize(-30);//減少30

 

class MyThreadJob : public ThreadJob //線程對象從ThreadJob擴展
{
public:
 virtual void DoJob(void *p)//自定義的虛函數
 {
  //.
 }
};
 MyThreadJob mt[10];
 ThreadPool tp;
 for(i=0; i<100 i++)
  tp.Call(mt + i);//tp.Call(mt + i, para);

posted @ 2009-02-02 16:28 micheal's tech 閱讀(6096) | 評論 (0)編輯 收藏

多線程同步機制摘要

Posted on 2007-04-03 19:34 kk 閱讀(1306) 評論(0)  編輯 收藏 引用 所屬分類: IT
  Critical Section

Critical section(臨界區)用來實現“排他性占有”。適用范圍是單一進程的各線程之間。它是:

·         一個局部性對象,不是一個核心對象。

·         快速而有效率。

·         不能夠同時有一個以上的critical section被等待。

·         無法偵測是否已被某個線程放棄。

Mutex

Mutex是一個核心對象,可以在不同的線程之間實現“排他性占有”,甚至幾十那些現成分屬不同進程。它是:

·         一個核心對象。

·         如果擁有mutex的那個線程結束,則會產生一個“abandoned”錯誤信息。

·         可以使用Wait…()等待一個mutex。

·         可以具名,因此可以被其他進程開啟。

·         只能被擁有它的那個線程釋放(released)。

Semaphore

Semaphore被用來追蹤有限的資源。它是:

·         一個核心對象。

·         沒有擁有者。

·         可以具名,因此可以被其他進程開啟。

·         可以被任何一個線程釋放(released)。

Event Object

Event object通常使用于overlapped I/O,或用來設計某些自定義的同步對象。它是:

·         一個核心對象。

·         完全在程序掌控之下。

·         適用于設計新的同步對象。

·         “要求蘇醒”的請求并不會被儲存起來,可能會遺失掉。

·         可以具名,因此可以被其他進程開啟。

Interlocked Variable

如果Interlocked…()函數被使用于所謂的spin-lock,那么他們只是一種同步機制。所謂spin-lock是一種busy loop,被預期在極短時間內執行,所以有最小的額外負擔(overhead)。系統核心偶爾會使用他們。除此之外,interlocked variables主要用于引用技術。他們:

·         允許對4字節的數值有些基本的同步操作,不需動用到critical section或mutex之類。

·         在SMP(Symmetric Multi-Processors)操作系統中亦可有效運作。


posted @ 2009-02-02 14:35 micheal's tech 閱讀(737) | 評論 (0)編輯 收藏

高性能服務器的多線程策略


(一)線程數量與線程池模型
  參見:high-performance server design. http://pl.atyp.us/content/tech/servers.html

  頻繁的上下文切換,會導致系統性能嚴重下降,而產生過多的切換大致有兩個原因:
1)過多的線程數量。這會使系統性能呈指數級的下降。對于每連接一個線程的系統而言,這也是為什么性能會變差的原因。一個具有可伸縮性的系統,它的唯一 可行的選擇,就是限制運行線程的數量。一般而言,這個值應該小于或等于處理器的數目。(說明,在boost網絡庫asio提供的example中,有一個 關于這種實現的很好的例子)
  2)所使用的線程池及事件模型。最簡單的一種模型通常是這個樣子:一個偵聽線程異步地接收請求,并在隊列中進行緩 沖。另外一組工作者線程則負責處理這些請求。這是一個不錯的模型,缺點就是每處理一個請求一般要經過兩次線程切換(加上對請求的回復)。為了避免這種缺 點,一個線程就必須具備偵聽者和工作者兩種角色,可以采用稱之謂“領導者/跟隨者”的模型。一個線程作為領導者,來進行監聽,當收到請求時,它選出一個跟 隨者線程作為新的領導者進行偵聽,自己則對請求進行處理,結束后,到跟隨者隊列中進行等待。

(二)多線程的內存池優化

普通的內存池一旦應用到多線程中,都面臨著鎖競爭的問題,在stlport所做的對于字符串性能的測試中,當使用兩個線程時,它所使用的內存池 node_allocator性能已經出現明顯的下降。所以對于多線程而言,一個線程一個內存池是一個很好的選擇。要實現這種設計,面臨的第一個問題,是 內存塊的跨線程使用問題,即一個內存塊,可能在A線程中申請,但可能在B線程中釋放。
  在GCC的STL實現libstdc++中,有一個多線程內存池的實現(mt_allocator)。它是node_allocator(現在叫pool_allocator) 的多線程版本。它還有一個優點就是所有參數都是可配置的。
  它的設計思路如下:每個線程一個內存池,同時還有一個全局的內存池。每個線程可以訪問自己的內存池,同時可在鎖保護下訪問全局內存池。申請的每一個內存塊中,都有一個線程ID,以標明是從哪個線程中申請的。
  申請過程:首先向所在線程申請,若本線程沒有空閑塊,則向全局內存池申請。
  釋放過程:直接歸還到本線程的空閑鏈中。還有一個問題,為了防止線程內存池之間的不均衡,或者某一個線程中的空閑鏈過長,可以設置一個水位標,當超過這個水位標時,把釋放的內存直接歸還到全局內存池中。

posted @ 2009-01-12 16:38 micheal's tech 閱讀(397) | 評論 (0)編輯 收藏


"placement new"? Embarrassed它 到底是什么東東呀?我也是最近幾天才聽說,看來對于C++我還差很遠呀!placement new 是重載operator new的一個標準、全局的版本,它不能被自定義的版本代替(不像普通的operator new和operator delete能夠被替換成用戶自定義的版本)。

它的原型如下:
void *operator new( size_t, void *p ) throw()  { return p; }

首先我們區分下幾個容易混淆的關鍵詞:new、operator new、placement new
new和delete操作符我們應該都用過,它們是對中的內存進行申請和釋放,而這兩個都是不能被重載的。要實現不同的內存分配行為,需要重載operator new,而不是new和delete。I dont know

看如下代碼:
class MyClass {…};
MyClass * p=new MyClass;

這里的new實際上是執行如下3個過程:


1. 調用operator new分配內存 ;2. 調用構造函數生成類對象;3. 返回相應指針。

operator new就像operator+一樣,是可以重載的,但是不能在全局對原型為void operator new(size_t size)這個原型進行重載,一般只能在類中進行重載。如果類中沒有重載operator new,那么調用的就是全局的::operator new來完成堆的分配。同理,operator new[]、operator delete、operator delete[]也是可以重載的,一般你重載的其中一個,那么最后把其余的三個都重載一遍。

至于placement new才是本文的重點。其實它也只是operator new的一個重載的版本,只是我們很少用到它。如果你想在已經分配的內存中創建一個對象,使用new時行不通的。也就是說placement new允許你在一個已經分配好的內存中(棧或者堆中)構造一個新的對象。原型中void*p實際上就是指向一個已經分配好的內存緩沖區的的首地址。

我們知道使用new操作符分配內存需要在堆中查找足夠大的剩余空間,這個操作速度是很慢的,而且有可能出現無法分配內存的異常(空間不夠)。 placement new就可以解決這個問題。我們構造對象都是在一個預先準備好了的內存緩沖區中進行,不需要查找內存,內存分配的時間是常數;而且不會出現在程序運行中途 出現內存不足的異常。所以,placement new非常適合那些對時間要求比較高,長時間運行不希望被打斷的應用程序。

使用方法如下:
1. 緩沖區提前分配
可以使用堆的空間,也可以使用棧的空間,所以分配方式有如下兩種:
class MyClass {…};
char *buf=new char[N*sizeof(MyClass)+ sizeof(int) ] ; 或者char buf[N*sizeof(MyClass)+ sizeof(int) ];

2. 對象的構造
MyClass * pClass=new(buf) MyClass;

3. 對象的銷毀
一旦這個對象使用完畢,你必須顯式的調用類的析構函數進行銷毀對象。但此時內存空間不會被釋放,以便其他的對象的構造。
pClass->~MyClass();

4. 內存的釋放
如果緩沖區在堆中,那么調用delete[] buf;進行內存的釋放;如果在棧中,那么在其作用域內有效,跳出作用域,內存自動釋放。

注意:

  • 在C++標準中,對于placement operator new []有如下的說明: placement operator new[] needs implementation-defined amount of additional storage to save a size of array. 所以我們必須申請比原始對象大小多出sizeof(int)個字節來存放對象的個數,或者說數組的大小。
  • 使用方法第二步中的new才是placement new,其實是沒有申請內存的,只是調用了構造函數,返回一個指向已經分配好的內存的一個指針,所以對象銷毀的時候不需要調用delete釋放空間,但必須調用析構函數銷毀對象。

posted @ 2009-01-08 20:56 micheal's tech 閱讀(1632) | 評論 (0)編輯 收藏

http://m.shnenglu.com/dyj057/archive/2005/09/20/346.html

大家都知道,在用C++來實現Singleton模式的時候通常把構造函數聲明為私有的或者保護的。同時聲明一個公有的靜態的偽構造函數,通過它來調用真正的構造函數。在實現這個偽構造函數的時候通常有兩種方式:  
  class   Singleton;  
   
  static   Singleton&   Singleton:;fakeSingleton()  
  {  
          static   Singleton   s;  
          return   s;  
  }  
  第二種方式:  
  class   Singleton{  
  public:  
  static   Singleton*   fakeSingleton();  
  ...  
  private:  
  Singleton();  
  static   Singleton   *   _instance;  
  }  
  Singleton*   Singleton::fakesinketon()  
  {  
        if(   _instance==NULL)  
                  _instance=new   Singleton();  
          return   _instance;  
  }  
  對于這兩種方式我覺得第一種更好一些,理由是,如果有兩個以上的線程同時訪問偽構造函數的時候有可能同時進入if   控制塊,這樣就有可能產生兩個實例!!因此必須采用特殊的保護機制來控制同步。而第一種方式不存在這樣的問題。  
   
  請高手指點!我不明白的是,為什么書上的例子還較多的采用第二種方法?莫非它有自己的優勢??  
   

posted @ 2009-01-06 16:06 micheal's tech 閱讀(1599) | 評論 (7)編輯 收藏

貪心法的基本思路:  
   
  從問題的某一個初始解出發逐步逼近給定的目標,以盡可能快的地求得更好的解。當達到某算法中的某一步不能再繼續前進時,算法停止。  
  該算法存在問題:  
  1.   不能保證求得的最后解是最佳的;  
  2.   不能用來求最大或最小解問題;  
  3.   只能求滿足某些約束條件的可行解的范圍。 實現該算法的過程:  
  從問題的某一初始解出發;
  
  while   能朝給定總目標前進一步   do  
  求出可行解的一個解元素;  
  由所有解元素組合成問題的一個可行解

貪心算法最經典的例子,給錢問題。  
  比如中國的貨幣,只看元,有1元2元5元10元20、50、100  
   
  如果我要16元,可以拿16個1元,8個2元,但是怎么最少呢?  
  如果用貪心算,就是我每一次拿那張可能拿的最大的。  
  比如16,我第一次拿20拿不起,拿10元,OK,剩下6元,再拿個5元,剩下1元  
  也就是3張   10、5、1。  
   
  每次拿能拿的最大的,就是貪心。  
   
  但是一定注意,貪心得到的并不是最優解,也就是說用貪心不一定是拿的最少的張數  
  貪心只能得到一個比較好的解,而且貪心算法很好想得到。  
  再注意,為什么我們的錢可以用貪心呢?因為我們國家的錢的大小設計,正好可以使得貪心算法算出來的是最優解(一般是個國家的錢幣都應該這么設計)。如果設計成別的樣子情況就不同了  
  比如某國的錢幣分為   1元3元4元  
  如果要拿6元錢   怎么拿?貪心的話   先拿4   再拿兩個1     一共3張錢  
  實際最優呢?   兩張3元就夠了  


求最優解的問題,從根本上說是一種對解空間的遍歷。最直接的暴力分析容易得到,最優解的解空間通常都是以指數階增長,因此暴力窮舉都是不可行的。
最優解問題大部分都可以拆分成一個個的子問題,把解空間的遍歷視作對子問題樹的遍歷,則以某種形式對樹整個的遍歷一遍就可以求出最優解,如上面的分析,這是不可行的。
貪心和動態規劃本質上是對子問題樹的一種修剪。兩種算法要求問題都具有的一個性質就是“子問題最優性”。即,組成最優解的每一個子問題的解,對 于這個子問題本身肯定也是最優的。如果以自頂向下的方向看問題樹(原問題作根),則,我們每次只需要向下遍歷代表最優解的子樹就可以保證會得到整體的最優 解。形象一點說,可以簡單的用一個值(最優值)代表整個子樹,而不用去求出這個子樹所可能代表的所有值。
動態規劃方法代表了這一類問題的一般解法。我們自底向上(從葉子向根)構造子問題的解,對每一個子樹的根,求出下面每一個葉子的值,并且以其中 的最優值作為自身的值,其它的值舍棄。動態規劃的代價就取決于可選擇的數目(樹的叉數)和子問題的的數目(樹的節點數,或者是樹的高度?)。
貪心算法是動態規劃方法的一個特例。貪心特在,可以證明,每一個子樹的根的值不取決于下面葉子的值,而只取決于當前問題的狀況。換句話說,不需 要知道一個節點所有子樹的情況,就可以求出這個節點的值。通常這個值都是對于當前的問題情況下,顯而易見的“最優”情況。因此用“貪心”來描述這個算法的 本質。由于貪心算法的這個特性,它對解空間樹的遍歷不需要自底向上,而只需要自根開始,選擇最優的路,一直走到底就可以了。這樣,與動態規劃相比,它的代 價只取決于子問題的數目,而選擇數目總為1。


posted @ 2008-11-18 11:20 micheal's tech 閱讀(3538) | 評論 (0)編輯 收藏

僅列出標題
共8頁: 1 2 3 4 5 6 7 8 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              欧美成人黑人xx视频免费观看| 99天天综合性| 麻豆国产精品777777在线| 制服丝袜激情欧洲亚洲| 夜久久久久久| 亚洲午夜视频在线| 亚洲综合好骚| 欧美一区综合| 猛干欧美女孩| 欧美人与性动交cc0o| 欧美视频日韩| 国产手机视频一区二区| 一区在线电影| 亚洲片在线观看| 亚洲影视中文字幕| 久久久久国产精品一区三寸| 欧美~级网站不卡| 亚洲免费av观看| 欧美一区二区三区视频免费播放 | 一区二区三区四区五区精品视频| 亚洲欧洲一区二区三区| 欧美91大片| 日韩视频一区二区三区| 午夜日韩激情| 欧美精选午夜久久久乱码6080| 国产精品久久久久一区二区三区| 激情欧美日韩一区| 亚洲一区欧美激情| 欧美电影专区| 午夜精品视频在线观看一区二区| 久久中文在线| 国产伦理一区| 日韩视频一区二区三区在线播放免费观看 | 亚洲免费观看高清完整版在线观看熊| 亚洲欧美综合另类中字| 欧美黄色小视频| 午夜视频久久久久久| 欧美精品福利在线| 亚洲国产一区二区在线| 亚洲天堂成人在线视频| 久久视频一区二区| 亚洲性感美女99在线| 欧美韩国在线| 亚洲成人影音| 久久精品综合网| 亚洲网站在线观看| 欧美精品二区| 亚洲伦理在线免费看| 免费久久久一本精品久久区| 亚洲在线观看视频网站| 欧美三级午夜理伦三级中文幕| 1024成人| 免费中文日韩| 久久精品亚洲| 红桃视频国产精品| 久久亚洲综合色一区二区三区| 亚洲女人av| 国产精品尤物福利片在线观看| 亚洲在线网站| 亚洲桃色在线一区| 国产精品人成在线观看免费 | 亚洲第一页中文字幕| 久久久久成人精品| 久久福利毛片| 国产在线欧美| 久久综合亚州| 麻豆成人av| 日韩天堂在线视频| 亚洲精品日韩综合观看成人91| 欧美不卡视频一区发布| 亚洲每日在线| 亚洲视频中文字幕| 国产日韩欧美不卡| 久久一区二区精品| 免费不卡视频| 一区二区三区日韩欧美精品| 亚洲免费观看高清完整版在线观看熊 | 欧美体内谢she精2性欧美| 亚洲午夜激情| 亚洲一区中文| 一区二区视频免费在线观看| 美女黄网久久| 欧美日本一道本在线视频| 亚洲免费小视频| 久久久久久穴| 艳妇臀荡乳欲伦亚洲一区| 亚洲视频在线观看三级| 国产又爽又黄的激情精品视频| 欧美第一黄色网| 国产精品www.| 欧美成人国产一区二区| 欧美日韩视频专区在线播放 | 欧美.日韩.国产.一区.二区| 欧美不卡一区| 欧美有码在线视频| 老鸭窝毛片一区二区三区| 9人人澡人人爽人人精品| 亚洲欧美国产另类| 亚洲日本欧美日韩高观看| 亚洲午夜影视影院在线观看| 在线精品视频一区二区| 一本色道久久综合亚洲精品不卡| 韩国av一区二区三区四区| 亚洲精品一区二区网址| 狠狠色丁香婷婷综合久久片| 亚洲精品小视频在线观看| 国内精品久久久| 亚洲视频狠狠| 日韩视频不卡| 毛片基地黄久久久久久天堂| 欧美在线观看视频| 欧美日韩国产影片| 欧美福利视频在线| 国产在线观看91精品一区| 亚洲线精品一区二区三区八戒| 亚洲国产精品国自产拍av秋霞| 亚洲综合欧美| 亚洲午夜性刺激影院| 久久久久久久欧美精品| 欧美一区二区三区视频| 亚洲人午夜精品免费| 国产婷婷一区二区| 久久免费视频网| 欧美黄色一区| 亚洲精品一区二区三区婷婷月| 夜夜精品视频| 亚洲精品黄色| 激情成人中文字幕| 亚洲在线第一页| 亚洲影院在线| 欧美视频一区在线| 亚洲欧洲另类国产综合| 亚洲国产综合在线| 久久亚洲精选| 免费日本视频一区| 伊人激情综合| 久久久久久久久伊人| 麻豆成人综合网| 在线观看欧美日本| 麻豆成人精品| 91久久久久久| 亚洲激情偷拍| 欧美国产日韩在线| 亚洲国产日韩一级| 亚洲国产日日夜夜| 欧美成人影音| 亚洲精品黄色| 午夜精品影院在线观看| 国产精品一二三四区| 欧美亚洲网站| 久久综合给合久久狠狠色| 日韩西西人体444www| 亚洲一线二线三线久久久| 性欧美18~19sex高清播放| 国产精品国产馆在线真实露脸 | 欧美一区午夜精品| 久久综合给合| 亚洲乱码久久| 国产精品久久久久久久午夜片 | 亚洲美女色禁图| 欧美日韩视频在线一区二区观看视频| 中文网丁香综合网| 久久精品论坛| 亚洲精品视频免费在线观看| 欧美日韩亚洲国产一区| 亚洲天堂男人| 久久综合伊人77777蜜臀| 亚洲美女少妇无套啪啪呻吟| 国产精品永久免费| 免费一区二区三区| 亚洲视频专区在线| 欧美激情精品久久久| 亚洲欧美国产日韩天堂区| 原创国产精品91| 欧美日韩专区| 老色批av在线精品| 国产精品日韩电影| 欧美一区二区三区男人的天堂 | 亚洲精品欧美在线| 午夜国产一区| 亚洲人成在线免费观看| 国产精品一区二区久久| 欧美成人精品在线观看| 亚洲欧美日韩一区在线| 亚洲高清一区二| 久久精品亚洲一区二区| 亚洲乱码久久| 在线精品视频免费观看| 国产免费一区二区三区香蕉精| 欧美α欧美αv大片| 欧美在线亚洲在线| 亚洲图片欧美日产| 亚洲日本成人女熟在线观看| 久久久精品国产一区二区三区 | 亚洲视频一二区| 亚洲国产精品黑人久久久| 国产专区欧美精品| 国产精品露脸自拍| 欧美日韩一区不卡| 欧美精品色网|