C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: bitmapでメモリが壊れる現象


(過去ログ 135 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■79856 / inTopicNo.1)  bitmapでメモリが壊れる現象
  
□投稿者/ だんご (1回)-(2016/05/24(Tue) 01:46:40)

分類:[.NET 全般] 

GIF画像をインターネットから取得し、そのストリームからbitmapを作成しています。
ここからbitmapに直接アクセスするLockBitsを行うのですが、たまにメモリが破壊されているという例外が発生します。
ですが、インターネットから取得した際エラーが出ないため事前に例外の検出ができない状態です。また、画像のフォーマットを調べる方法でも防ぐことはできませんでした。
何か解決方法はありますでしょうか。


例外内容は以下の通りです。
「型 'System.AccessViolationException' のハンドルされていない例外が System.Drawing.dll で発生しました
追加情報:保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。」

ソースについては以下のサイトを参考にしました。
http://homepage2.nifty.com/nonnon/SoftSample/VB.NET/SampleBitmapPlus.html


引用返信 編集キー/
■79857 / inTopicNo.2)  Re[1]: bitmapでメモリが壊れる現象
□投稿者/ kiku (103回)-(2016/05/24(Tue) 10:10:33)
大きく分けて下記の処理をしていると理解しました。
 1.インターネットからGIF画像を取得。
 2.取得したGIF画像を加工。

「上記1で正しく画像を取得できていないため、上記2の箇所で例外が発生した」
ということまで確認できたということでしょうか?

もしそうであるならば、どのようにGIF画像を取得しているのかを提示し、
どの箇所で例外が発生すべきだけど、発生しないということを
提示すべきかと思います。

引用返信 編集キー/
■79866 / inTopicNo.3)  Re[2]: bitmapでメモリが壊れる現象
□投稿者/ だんご (2回)-(2016/05/25(Wed) 00:16:15)
No79857 (kiku さん) に返信
> 大きく分けて下記の処理をしていると理解しました。
>  1.インターネットからGIF画像を取得。
>  2.取得したGIF画像を加工。
>
> 「上記1で正しく画像を取得できていないため、上記2の箇所で例外が発生した」
> ということまで確認できたということでしょうか?
>
> もしそうであるならば、どのようにGIF画像を取得しているのかを提示し、
> どの箇所で例外が発生すべきだけど、発生しないということを
> 提示すべきかと思います。
>

失礼いたしました。

GIF画像はWebClientのOpenReadAsyncで取得し、OpenReadCompletedイベントでbitmap = New Bitmap(e.Result)として生成しております。
また、もちろんe.Errorとe.Cancelledの値は確認しています。

例外の発生場所については、前記のソースURLの
BeginAccess関数内のLockBits、GetPixel関数内の
Dim b As Byte = Runtime.InteropServices.Marshal.ReadByte(adr, pos + 0)
が主な点になります。稀に発生箇所が表示されない時もあります。
引用返信 編集キー/
■79880 / inTopicNo.4)  Re[3]: bitmapでメモリが壊れる現象
□投稿者/ 魔界の仮面弁士 (724回)-(2016/05/26(Thu) 10:22:21)
No79866 (だんご さん) に返信
> GIF画像はWebClientのOpenReadAsyncで取得し、OpenReadCompletedイベントでbitmap = New Bitmap(e.Result)として生成しております。
もしもログイン処理等が不要な場合には、
 PictureBox1.WaitOnLoad = False
 PictureBox1.LoadAsync("http://home.hiroshima-u.ac.jp/kojiok/1bit.gif")
だけでも良いかもしれません。


> ここからbitmapに直接アクセスするLockBitsを行うのですが、
Animated GIF だった場合は、LockBits する前に SelectActiveFrame を呼び出す必要があります。
(LockBits 中はフレームを変更できないためです)

SelectActiveFrame を呼ばなかった場合、最初のフレームの画像しか処理できません。


> たまにメモリが破壊されているという例外が発生します。
「たまに」の再現性を教えてください。

同じ画像でも、時折失敗するということでしょうか。
それとも、特定の画像が常に失敗するということでしょうか。
あるいは、実行する PC環境によって成否が異なるということでしょうか。

> BeginAccess関数内のLockBits、GetPixel関数内の
> Dim b As Byte = Runtime.InteropServices.Marshal.ReadByte(adr, pos + 0)
> が主な点になります。稀に発生箇所が表示されない時もあります。
そのエラーが発生する画像を公開する事はできますか?
引用返信 編集キー/
■79890 / inTopicNo.5)  Re[4]: bitmapでメモリが壊れる現象
□投稿者/ だんご (3回)-(2016/05/26(Thu) 18:51:49)
No79880 (魔界の仮面弁士 さん) に返信
> ■No79866 (だんご さん) に返信
>>GIF画像はWebClientのOpenReadAsyncで取得し、OpenReadCompletedイベントでbitmap = New Bitmap(e.Result)として生成しております。
> もしもログイン処理等が不要な場合には、
>  PictureBox1.WaitOnLoad = False
>  PictureBox1.LoadAsync("http://home.hiroshima-u.ac.jp/kojiok/1bit.gif")
> だけでも良いかもしれません。
>

当初はその方法で取得していましたが、取得する画像の数が数枚あるのと、必ずしも画像を表示するわけではないことなどから管理面を重視して変更しました。また画像は毎秒取得するため、読み込みの完了の通知が欲しいというのもあります。(もしあるのでしたら教えてください…)


>>ここからbitmapに直接アクセスするLockBitsを行うのですが、
> Animated GIF だった場合は、LockBits する前に SelectActiveFrame を呼び出す必要があります。
> (LockBits 中はフレームを変更できないためです)
>
> SelectActiveFrame を呼ばなかった場合、最初のフレームの画像しか処理できません。
>

取得するGIF画像はアニメーションではないため大丈夫です。


>>たまにメモリが破壊されているという例外が発生します。
> 「たまに」の再現性を教えてください。
>
> 同じ画像でも、時折失敗するということでしょうか。
> それとも、特定の画像が常に失敗するということでしょうか。
> あるいは、実行する PC環境によって成否が異なるということでしょうか。

起きるときは起きますが起きない時は全く起きないといった状況です。
頻度は1日2〜3時間の製作作業で3日に1〜2回くらいでしょうか。
画像は毎秒取得するため同じとは言えないかと思います。
すみませんがPCが1台のみですので別のPCでは試せていません。


>>BeginAccess関数内のLockBits、GetPixel関数内の
>>Dim b As Byte = Runtime.InteropServices.Marshal.ReadByte(adr, pos + 0)
>>が主な点になります。稀に発生箇所が表示されない時もあります。
> そのエラーが発生する画像を公開する事はできますか?

http://www.kmoni.bosai.go.jp/new/
こちらの各地点に色がついた画像です。
引用返信 編集キー/
■79896 / inTopicNo.6)  Re[5]: bitmapでメモリが壊れる現象
□投稿者/ 魔界の仮面弁士 (728回)-(2016/05/26(Thu) 21:33:38)
2016/05/26(Thu) 21:35:30 編集(投稿者)

No79890 (だんご さん) に返信
> 画像は毎秒取得するため同じとは言えないかと思います。
なるほど。その場合は PictureBox を経由させない方が扱いやすいですね。


> 読み込みの完了の通知が欲しいというのもあります。
一応、LoadCompleted イベントというものが用意されています。


> 起きるときは起きますが起きない時は全く起きないといった状況です。
LockBits で確保されているメモリ領域外にアクセスされた状況かと予想しています。

何らかの理由で、画像データが最後まで受信できていなかったという可能性は
既に調査済みでしょうか。たとえば、データ末尾が 0x3B では無かったケースなど。

あとは、画素の読み取りのみを目的としているのあれば、ImageLockMode を
ReadOnly モードに置き換えてみるとか。


> 頻度は1日2〜3時間の製作作業で3日に1〜2回くらいでしょうか。
現時点では、GDI+ の不具合なのか、画像自体の問題なのか分からないので、
まずはエラー発生時の画像データが欲しいところですね。

CopyTo メソッドを用いるなどして、e.Result を MemoryStream あたりに
キャッシュしてから Bitmap に渡すようにし、例外が発生した場合は、
要因となった MemoryStream および、Scan0 に対するオフセット値(Dim pos As Integer)を
ファイルに保存するなどして、記録を取れないでしょうか。
引用返信 編集キー/
■79897 / inTopicNo.7)  Re[6]: bitmapでメモリが壊れる現象
□投稿者/ だんご (4回)-(2016/05/26(Thu) 21:47:20)
No79896 (魔界の仮面弁士 さん) に返信
> 2016/05/26(Thu) 21:35:30 編集(投稿者)
> 何らかの理由で、画像データが最後まで受信できていなかったという可能性は
> 既に調査済みでしょうか。たとえば、データ末尾が 0x3B では無かったケースなど。

データの最初の部分しか見ていませんでした。この方法でエラーが起きないか試してみます。


> あとは、画素の読み取りのみを目的としているのあれば、ImageLockMode を
> ReadOnly モードに置き換えてみるとか。

これは既に置き換えていますが関係ありませんでした。


>>頻度は1日2〜3時間の製作作業で3日に1〜2回くらいでしょうか。
> 現時点では、GDI+ の不具合なのか、画像自体の問題なのか分からないので、
> まずはエラー発生時の画像データが欲しいところですね。
>
> CopyTo メソッドを用いるなどして、e.Result を MemoryStream あたりに
> キャッシュしてから Bitmap に渡すようにし、例外が発生した場合は、
> 要因となった MemoryStream および、Scan0 に対するオフセット値(Dim pos As Integer)を
> ファイルに保存するなどして、記録を取れないでしょうか。

わかりました。やってみます。
とりあえず末尾の0x3Bの判定でしばらくエラーが起きないか見てみます。
エラーが起きないようでしたらそのまま解決にさせていただきます。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -