OpenCVのライブラリには要注意

ちょっとはまってしまったネタなので書いてみます。

OpenCVのライブラリにある「結果データをSTLにあるvectorで返す」処理が

いろいろと知らないと簡単にバグを起こして立ち往生しますので。

ちなみに、この問題は今のバージョン(OpenCV 2.4系)だとVisualStudio2005を使ってやろうとしている人がはまります。

VisualStudio2008やVisualStudio2010ならばすでにそれようにコンパイルされたライブラリもしくはDLLがあるのでそれを使えばこの問題にはまることはあまりありません。

それでも、DLLを使うときにはやはり注意する必要があります。

処理としては、典型的なのがcv::imencodeを使ったイメージの変換作業です。

メモリ上で変換を行ってくれるのでOpenCVでは結果の送受信等に使われます。が、

STLのvectorが動的確保を行うときにはランタイム内のメモリ処理が使われる

というか、STLのライブラリがメモリ確保を行うときは基本的にはnew演算子を使ってメモリ確保を行うことと同じような動作を行います。

ここにとんでもない落とし穴があります。

この話題については過去にちょっと触れている問題ですが、これが大きくなってしまった物です。

VisualStudio2008(or2010)で構築されたDLLをVisualStudio2005で構築されたEXEに連結すると?

と言う話です。EXE側はもちろんVisualStudio2005のランタイムライブラリを連結しますのでそれに準拠したメモリ処理が行われます。

ところが、DLL側はVisualStudio2008のランタイムライブラリを連結しますので、相互にまたいでのメモリ処理に互換性が全くなくなります。

そうすると、初めに上げたパターンである「OpenCVのライブラリ内でvectorによるメモリの動的確保を行い、実行ファイル側でそのメモリを解放しようとする」と、状態が整合できないのがわかると思います。

ちなみに、両方ともVisualStudio2008であったとしても、

  • EXE側には静的ランタイムライブラリを結合している
  • DLL側も同様に(自分だけで)静的ランタイムライブラリを結合している

だと、ランタイム内にそれぞれがヒープメモリを管理しているならやはり整合はとれません。大変です。

OpenCVのvectorを使う処理を使うときは「静的リンク+ランタイムライブラリをそろえる」もしくは「動的リンク+同一のDLLのランタイムライブラリを使用する」とする必要があり

ちなにみ、OpenCV2.4ではVisualStudio2005のライブラリはありませんので、CMakeを使ってVisualStudio2005のプロジェクトを作成してコンパイルする必要があります。

それでコンパイルして静的リンクを行うのであれば同一のメモリ管理で扱われるのでめでたしめでたし、となります。

いわゆる「DLLでメモリをnewで確保して、EXEでメモリをdeleteで解放する」の問題の解決パターンになります。

vectorをライブラリに渡して結果を受け取るときにはこの問題に気をつけましょう~~~

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

この記事のトラックバック用URL