Feeds:
文章
迴響

Archive for 2008 年 01 月

今天同事遇到一個奇怪的問題,環境是 Windows 2000 Server + IIS,當網頁內包含下面的 JScript.Encode 內容時

<SCRIPT FOR="wgmplayer" EVENT="EndOfStream(lResult)" LANGUAGE="JScript.Encode">#@~^OQAAAA==@#@&@!Z O@#@&k6`hslHAznmonZ{JXdJ*PxaO/mv#I@#@&R @*@#@&MgwAAA==^#~@</SCRIPT>

網頁會出不來,可是如果將內容改為

<SCRIPT FOR="wgmplayer" EVENT="EndOfStream(lResult)" LANGUAGE="JScript.Encode">

#@~^OQAAAA==@#@&@!Z O@#@&k6`hslHAznmonZ{JXdJ*PxaO/mv#I@#@&R @*@#@&MgwAAA==^#~@

</SCRIPT>

或是

<SCRIPT FOR="wgmplayer" EVENT="EndOfStream(lResult)" LANGUAGE="JScript.Encode"><!– #@~^OQAAAA==@#@&@!Z O@#@&k6`hslHAznmonZ{JXdJ*PxaO/mv#I@#@&R @*@#@&MgwAAA==^#~@ –></SCRIPT>

就可以正常呈現,我個人是比較推薦第一種寫法,因為較具可讀性。

不過,如果上述網頁放置在 Apache 上述三種寫法都可以正常呈現。真不知道 IIS 是怎麼發生這樣的錯誤~

廣告

Read Full Post »

繼[1]之後,又繼續嘗試了 object_pool ,這個比較符合我的預期和需要,他能夠正常的解構物件,也會自動釋放配置的記憶體相當的棒。object_pool 從 pool 繼承下來,並加上物件管理機制,應該可以達到我的自動解構目的。

改寫[1] 的範例如下:

#include <vcl.h>
#include <iostream>
#include <vector>
#include <boost/pool/object_pool.hpp>
#pragma hdrstop
#include "Unit2.h"
//—————————————————————————

#pragma argsused
class A{
public:
    A(int id_){
        id =id_;
        std::cout << "A()" << id << std::endl;
    }

    ~A(){
        std::cout << "~A()" << id << std::endl;
    }
private:
    int id;
};

typedef boost::object_pool<A> APool;
APool& GetAPool(){
    static APool pool;
    return pool;
}

A* Create(int id){

    return GetAPool().construct(id); // 物件建構
}

int main(int argc, char* argv[]){
    using std::vector;
    vector<A*> aCol;
    aCol.push_back( Create(1) );
    aCol.push_back( Create(2) );
    for(vector<A*>::iterator iter = aCol.begin(); iter!=aCol.end(); ++iter){
//        delete *iter;
        GetAPool().destroy(*iter); // 觸發 ~A()
    }
    A* a = Create(3);
    GetAPool().destroy(a); // 觸發 ~A()

    aCol.clear();

    return 0;
}// ~object_pool 自動解構所有物件

從 object_pool 原始碼來看,destroy() 多了解構的程式,如下:

void destroy(element_type * const chunk)
{
  chunk->~T(); // 呼叫型別解構子
  free(chunk); // 釋放記憶體
}

在 ~object_pool 也會迭代呼叫每一個維護的 ~T(),如下:

template <typename T, typename UserAllocator>
object_pool<T, UserAllocator>::~object_pool()
{
  // handle trivial case
  if (!this->list.valid())
    return;

  details::PODptr<size_type> iter = this->list;
  details::PODptr<size_type> next = iter;

  // Start ‘freed_iter’ at beginning of free list
  void * freed_iter = this->first;

  const size_type partition_size = this->alloc_size();

  do
  {
    // increment next
    next = next.next();

    // delete all contained objects that aren’t freed

    // Iterate ‘i’ through all chunks in the memory block
    for (char * i = iter.begin(); i != iter.end(); i += partition_size)
    {
      // If this chunk is free
      if (i == freed_iter)
      {
        // Increment freed_iter to point to next in free list
        freed_iter = nextof(freed_iter);

        // Continue searching chunks in the memory block
        continue;
      }

      // This chunk is not free (allocated), so call its destructor
      static_cast<T *>(static_cast<void *>(i))->~T();
      // and continue searching chunks in the memory block
    }

    // free storage
    UserAllocator::free(iter.begin());

    // increment iter
    iter = next;
  } while (iter.valid());

  // Make the block list empty so that the inherited destructor doesn’t try to
  //  free it again.
  this->list.invalidate();
}

 

所以,如果你想要大量配置物件,而又想要他自動解構回收,就用 object_pool 吧~

參考資料
[1] Chui-Wen Chiu, "C++ boost::singleton_pool 會自動釋放記憶體但不會呼叫解構"

Read Full Post »

最近想利用 boost 改善程式的穩定性和效能,於是測試 pool 發現一個問題,以下是 CB6 + boost 1.35 寫的測試程式

#include <vcl.h>
#include <iostream>
#include <vector>
#include <boost/pool/singleton_pool.hpp>
#pragma hdrstop
#include "Unit2.h"
//—————————————————————————

#pragma argsused
class A{
public:
    A(int id_){
        id =id_;
        std::cout << "A()" << id << std::endl;
    }

    ~A(){
        std::cout << "~A()" << id << std::endl;
    }
private:
    int id;
};

typedef boost::singleton_pool<A, sizeof(A)> APool;
A* Create(int id){
    void* t = APool::malloc();
    return new (t) A(id);
}

int main(int argc, char* argv[]){
    using std::vector;
    vector<A*> aCol;
    aCol.push_back( Create(1) );
    aCol.push_back( Create(2) );
    for(vector<A*>::iterator iter = aCol.begin(); iter!=aCol.end(); ++iter){
//        delete *iter; // 觸發 ~A()
//        APool::free(*iter); // 不會觸發 ~A()
    }
    aCol.clear();

    A* a = Create(3);
    APool::free(a);// 不會觸發 ~A()

    APool::purge_memory();  // 不會觸發 ~A()

    return 0;
}

我原以為呼叫 free() 或 purge_memory() 會自動呼叫解構並釋放記憶體。但測試結果,只有在明確 delete 時才會觸發解構子

追蹤一下原始碼,當呼叫 purge_memory() 時,實際上他是呼叫 bool pool<UserAllocator>::purge_memory(),此部份的程式碼摘錄如下:

template <typename UserAllocator>
bool pool<UserAllocator>::purge_memory()
{
  details::PODptr<size_type> iter = list;

  if (!iter.valid())
    return false;

  do
  {
    // hold "next" pointer
    const details::PODptr<size_type> next = iter.next();

    // delete the storage
    UserAllocator::free(iter.begin()); // 釋放記憶體

    // increment iter
    iter = next;
  } while (iter.valid());

  list.invalidate();
  this->first = 0;

  return true;
}

從原始碼可看出他只有釋放配置的記體區塊,卻沒有自動呼叫解構子。

所以,使用 pool 或 singleton_pool 只能保證記憶體會完整的釋放,卻無法保證物件完整的解構~

因此, pool 和 singleton_pool 我覺得比較適合用於單純的記憶體配置,而非物件的建構 & 解構

Read Full Post »

FreeGrab 抓取米蘭婚紗照片

完整程式碼如下(milan.lua)

MODULE_NAME = "milan"
MODULE_VERSION = "0.0.1"
MODULE_REQUIRE_VERSION = "1.2.3.3"
MODULE_AUTHOR = "cwchiu@hotmail.com"
MODULE_LAST_UPDATE = "2008/01/28"
————————————————————————-
–main
————————————————————————-
function Download()
    local url = GetUrl()   
    local iRid = string.match(url, "iRid=(%d+)")
    if iRid ==nil then
        — download file
        if string.match(url, ‘/db/(%d+.jpg)’) == nil then
            UpdateLog(‘URL Error’)
            return false
        end

        return GetFile(url)
    end
    local DataTab = {}

    — get url
    local menu = ‘http://www.milan.com.tw/newlyweds/newlyweds_left.asp?iRid=’ .. iRid
    –UpdateLog( menu )
    GetHtml(menu);
    Compile("(.*)");
    local _, html = What()   
    local index = 1
    for str,int in string.gmatch( html, "change.'(%d+)") do
        local jpg_url = ‘http://www.milan.com.tw/db/’ .. str .. ‘.jpg’
        DataTab[index] = { url = jpg_url }
        index = index + 1
    end

    if index == 1 then UpdateLog("No Picture") return false end
    UpdateLog( index )
    — update data
    UpdatePhotoData(DataTab)

    return true
end

將 milan.lua 放置在 %freegrab%Modulesalbum

並在 %freegrab%Modulesconfig.lua 加入

freegrab.MODULE["www.milan.com.tw"]  = { name="milan", cat="album",
      home="http://www.milan.com.tw",
      charset="big5",
      fnformat="$url.$ext"}

以下為執行畫面

2008012801

2008012802 

相關文章

[1] Chui-Wen Chiu, "使用 Freegrab 抓取 ADrive 檔案"
[2] Chui-Wen Chiu, "使用FreeGrab 抓ITPub 的電子書"

Read Full Post »

最近又翻了一次 "Andrei Alexandrescu, Modern C++ Design",這次又有不同的感受,所謂的 Policy 編程技術,簡單的說就是 template + 多重繼承的技術。其中又有兩個關鍵名詞

Policy: 用來定義一個 Class 或 Class template 的介面

Hosts/Host Classes: 採用一個或多個 Policy,簡單的說就是 Policy 收納器

有這層基本概念後,我們可以利用這種技術,設計一個頗具彈性的程式,以下使用一個簡單的兩位數四則運算作為範例

/**
* Add Policy
*
*/
template< typename T>
struct AddCalc{
     T Add(T a, T b){
        return a+b;
     }
};

/**
* Sub Policy
*
*/
template< typename T>
struct SubCalc{
     T Sub(T a, T b){
        return a-b;
     }
};

/**
* Mul Policy
*
*/
template< typename T>
struct MulCalc{
     T Mul(T a, T b){
        return a*b;
     }
};

/**
* Div Policy
*
*/
template< typename T>
struct DivCalc{
     T Div(T a, T b){
        return a/b;
     }
};

/**
* Host Classes
*
*/
template<
    typename T = int,
    template<class> class AddPolicy = AddCalc,
    template<class> class SubPolicy = SubCalc,
    template<class> class MulPolicy = MulCalc,
    template<class> class DivPolicy = DivCalc
>
class Calculator
    : public AddPolicy<T>,
      public SubPolicy<T>,
      public MulPolicy<T>,
      public DivPolicy<T>
{
public:

};

/**
* Add Policy
*
*/
template< typename T>
struct ErrorAddCalc{
     T Add(T a, T b){
        return a+b+100;
     }
};

int main(int argc, char* argv[])
{
    typedef Calculator<int> IntCalculator;
    typedef Calculator<float> FloatCalculator;

    std::cout << "IntCalculator:n";
    IntCalculator ic;
    std::cout << ic.Add(100, 200) << std::endl; // 300
    std::cout << ic.Sub(100, 200) << std::endl; // -100
    std::cout << ic.Mul(100, 200) << std::endl; // 20000
    std::cout << ic.Div(100, 200) << std::endl << std::endl; // 0

    std::cout << "FloatCalculator:n";
    FloatCalculator fc;
    std::cout << fc.Add(100, 200) << std::endl; // 300
    std::cout << fc.Sub(100, 200) << std::endl; // -100
    std::cout << fc.Mul(100, 200) << std::endl; // 20000
    std::cout << fc.Div(100, 200) << std::endl << std::endl; // 0.5

    // 透過自訂 AddPolicy 改變行為
    typedef Calculator<int, ErrorAddCalc> ErrorCalculator;
    std::cout << "ErrorCalculator:n";
    ErrorCalculator ec;
    std::cout << ec.Add(100, 200) << std::endl << std::endl; // 400

    typedef Calculator<std::string> StringCalculator;
    StringCalculator sc;
    std::cout << sc.Add("Author: ", " Chui-Wen Chiu") << std::endl;
    std::cout << sc.Add("Blog: ", " http://chuiwenchiu.spaces.live.com") << std::endl;
    return 0;
}

從上述程式可發現,定義了一個如下的 Host Classes

template<
    typename T = int,
    template<class> class AddPolicy = AddCalc,
    template<class> class SubPolicy = SubCalc,
    template<class> class MulPolicy = MulCalc,
    template<class> class DivPolicy = DivCalc
>
class Calculator

這就是剛剛說得 template + 多重繼承的寫法。

第一個參數表示,這個計算器要處理的元素型別,因此,可透過測試程式的 IntCalculator 和 FloatCalculator 發現,如果你熟悉 STL/boost 那對於這個參數的用途應該很熟悉。重點是接下來的四個 Policy 參數,主要用來決定 Calculator 的行為。四個 Policy 的用途如下:

Add Policy: 定義 Add 介面,回傳兩參數運算後的值
Sub Policy: 定義 Sub 介面,回傳兩參數運算後的值
Mul Policy: 定義 Mul 介面,回傳兩參數運算後的值
Div Policy: 定義 Div 介面,回傳兩參數運算後的值

因為這些 Policy 皆為 Calculator 的 template 參數,所以,可以自訂符合介面的 Policy,例如上述的 ErrorCalculator。

由上述的簡單範例你是否對 C++ Policy 編程有點瞭解了呢?

Read Full Post »

當你多份文件要共用給同一群人時,這個功能你就會很需要。用法很簡單,先選取多份文件後,再點選分享,然後輸入合作者的 mail 即可。

2008012601

Read Full Post »

來源:電子郵件
作者:不詳

No Pain No Gain… Accept the Pain, Future will be Fruitful…
Don’t feel the work you are doing is pain, because there will be always a reason for that pain or work.

Read Full Post »

Older Posts »