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

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

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

Re[2]: Graphics.DrawLineでのオーバーフローについて


(過去ログ 138 を表示中)

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

■81145 / inTopicNo.1)  Graphics.DrawLineでのオーバーフローについて
  
□投稿者/ みくさわ (1回)-(2016/08/30(Tue) 22:27:56)

分類:[VB.NET/VB2005 以降] 

いつもお世話になっております。
表記件について質問があります。

開発環境はVB2008です。

Graphics.DrawLine(Pens.Red, Integer.MaxValue, 100, 1, 1)のコードを実行すると
オーバーフローエラーが発生します。
Integer.MaxValueの箇所を100とかにすると正常に動作することから、Integer.MaxValueで
オーバーフローが発生しているのは間違いないのですが、DrawLineの引数はInteger型なのに
何故という疑問があります。

上記エラーは、PictureBoxにグラフを描画する処理で、PictureBoxの領域外に向かって線を
描画しようとして発生しました。

Graphics.DrawLineに指定できる座標は、どこまでなのでしょうか?
(Graphics.ClipBoundsが可能領域かと思いましたが、MSDNに"クリッピング領域が無限の場合、
ClipBoundsプロパティは巨大な四角形の情報を返します"とあり、不安になって質問させて
もらいました。)

お手数ですが、宜しくお願い致します。

引用返信 編集キー/
■81146 / inTopicNo.2)  Re[1]: Graphics.DrawLineでのオーバーフローについて
□投稿者/ Hongliang (453回)-(2016/08/30(Tue) 23:19:03)
> Integer.MaxValueの箇所を100とかにすると正常に動作することから、Integer.MaxValueで
> オーバーフローが発生しているのは間違いないのですが、DrawLineの引数はInteger型なのに
> 何故という疑問があります。
引数がInteger型だからといって、あらゆるメソッドがIntegerの全値域を受け入れなければならないってこともないでしょう。
例えばTCPのポート番号を引数に取るなら、型としてはIntegerを使うでしょうが有効なのは0〜65535だけです。

> Graphics.DrawLineに指定できる座標は、どこまでなのでしょうか?
私のPCで試した所、正の大きい方は0x4000017fまでOKで0x40000180でアウトになりましたが、これは環境に依る可能性があるので、この値を前提にすべきではないでしょう。
MSDNにも特に記述はないようなので、これと言い切ることはできませんね。
// 2^23-1辺りまでの値域を使っておけばまず間違いないと思いますが。
引用返信 編集キー/
■81148 / inTopicNo.3)  Re[2]: Graphics.DrawLineでのオーバーフローについて
□投稿者/ 真田昌幸 (63回)-(2016/08/31(Wed) 09:14:03)
No81146 (Hongliang さん) に返信
>>Integer.MaxValueの箇所を100とかにすると正常に動作することから、Integer.MaxValueで
>>オーバーフローが発生しているのは間違いないのですが、DrawLineの引数はInteger型なのに
>>何故という疑問があります。
> 引数がInteger型だからといって、あらゆるメソッドがIntegerの全値域を受け入れなければならないってこともないでしょう。
> 例えばTCPのポート番号を引数に取るなら、型としてはIntegerを使うでしょうが有効なのは0〜65535だけです。

integerはVB2002以降は32bitかと
16bitなのはVB6までとVBA
引用返信 編集キー/
■81149 / inTopicNo.4)  Re[1]: Graphics.DrawLineでのオーバーフローについて
□投稿者/ 真田昌幸 (64回)-(2016/08/31(Wed) 09:16:58)
No81145 (みくさわ さん) に返信
> いつもお世話になっております。
> 表記件について質問があります。
>
> 開発環境はVB2008です。
>
> Graphics.DrawLine(Pens.Red, Integer.MaxValue, 100, 1, 1)のコードを実行すると
> オーバーフローエラーが発生します。
> Integer.MaxValueの箇所を100とかにすると正常に動作することから、Integer.MaxValueで
> オーバーフローが発生しているのは間違いないのですが、DrawLineの引数はInteger型なのに
> 何故という疑問があります。

Integer.MaxValue-1にするとどうなりますか?

引用返信 編集キー/
■81159 / inTopicNo.5)  Re[3]: Graphics.DrawLineでのオーバーフローについて
□投稿者/ Jitta (207回)-(2016/08/31(Wed) 10:37:15)
No81148 (真田昌幸 さん) に返信

>>引数がInteger型だからといって、あらゆるメソッドがIntegerの全値域を受け入れなければならないってこともないでしょう。
>>例えばTCPのポート番号を引数に取るなら、型としてはIntegerを使うでしょうが有効なのは0〜65535だけです。
>
> integerはVB2002以降は32bitかと
> 16bitなのはVB6までとVBA

はい?
TCPのポートは65535までですが?
自作クラスで、TCPのポート番号を受け取る引数の型に、short使わずint使うよね。でも、65535を超えるとエラーですよ。
何もおかしいことではないでしょう。
TcpClientクラスもInt32型を受け取ります。
だからってintmaxを指定したらを指定したら範囲外例外です。
引用返信 編集キー/
■81161 / inTopicNo.6)  Re[3]: Graphics.DrawLineでのオーバーフローについて
□投稿者/ 魔界の仮面弁士 (859回)-(2016/08/31(Wed) 10:43:40)
No81148 (真田昌幸 さん) に返信
> >>Integer.MaxValueの箇所を100とかにすると正常に動作することから、Integer.MaxValueで
> >>オーバーフローが発生しているのは間違いないのですが、DrawLineの引数はInteger型なのに
> >>何故という疑問があります。
>>引数がInteger型だからといって、あらゆるメソッドがIntegerの全値域を受け入れなければならないってこともないでしょう。
>>例えばTCPのポート番号を引数に取るなら、型としてはIntegerを使うでしょうが有効なのは0〜65535だけです。
> 
> integerはVB2002以降は32bitかと
> 16bitなのはVB6までとVBA

VBA は関係無いですよね。

0〜65535 を表せる最小の型は System.UInt16 ですが、
そのための引数を System.Int32 にするのは珍しいことではありません。

たとえば日付型で、13月や32日を指定できないのは明確ですが、
DateTime の Month プロパティは、Byte ではなく Integer ですよね。


TCP のポート番号は、
 0〜1023 :ウェルノウンポート番号
 〜49151 :登録済みポート番号
 〜65535 :動的・プライベート ポート番号
であり、この範囲外を認めないというだけの話です。



   【符号なし整数型】
(a) 0〜255
(b) 0〜65535
(c) 0〜4294967295
(d) 0〜18446744073709551615


   【符号付き整数型】
(e)                -128〜127
(f)              -32768〜32767
(g)         -2147483648〜2147483647
(h)-9223372036854775808〜9223372036854775807

----------------------------
     .NET     VB.NET    VBA         VARIANT
(a)  Byte     Byte      Byte        VT_UI1 (17)
(b)  UInt16   UShort    非サポート  VT_UI2 (18)
(c)  UInt32   UInteger  非サポート  VT_UI4 (19)
(d)  UInt64   ULong     非サポート  VT_UI8 (21)
(e)  SByte    SByte     非サポート  VT_I1  (16)
(f)  Int16    Short     Integer     VT_I2  (2)
(g)  Int32    Integer   Long        VT_I4  (3)
(h)  Int64    Long      LongLong    VT_I8  (20)

引用返信 編集キー/
■81162 / inTopicNo.7)  Re[1]: Graphics.DrawLineでのオーバーフローについて
□投稿者/ 魔界の仮面弁士 (860回)-(2016/08/31(Wed) 11:10:25)
No81145 (みくさわ さん) に返信
> Graphics.DrawLine(Pens.Red, Integer.MaxValue, 100, 1, 1)のコードを実行すると
> オーバーフローエラーが発生します。

内部的には、gdiplus.dll の GdipDrawLineI API を呼び出しているだけなので、
GDI+ 側の制限ということになりますね。実行環境によっても左右されそうです。


> (Graphics.ClipBoundsが可能領域かと思いましたが、MSDNに"クリッピング領域が無限の場合、
> ClipBoundsプロパティは巨大な四角形の情報を返します"とあり、不安になって質問させて
> もらいました。)

e.Graphics.Clip あるいは Graphics.SetClip に対して、無限な領域
―――たとえば Region.MakeInfinite() なリージョン―――が指定されて
いたとしても、ClipBounds は無限値ではなく、有限値を返すということですよね。

ClipBounds が返す「巨大な四角形」のサイズはまちまちなようで、
その時々で、たとえば以下のような範囲が返されてきました。
明確な上限値があるというわけではなさそうです。

{X=-4194304,Y=-4194304,Width=8388608,Height=8388608}
{X=-4194292,Y=-4194336,Width=8388608,Height=8388608}
{X=-4194292,Y=-4194329,Width=8388608,Height=8388608}
{X=-4194292,Y=-4194326,Width=8388608,Height=8388608}
{X=-4194292,Y=-4194319,Width=8388608,Height=8388608}
{X=-4194292,Y=-4194281,Width=8388608,Height=8388608}

ちなみに上記のいずれでも、
 Dim b = g.ClipBounds
 g.DrawLine(Pens.Red, b.Left, b.Top, b.Right, b.Bottom)
はエラーになりませんでした。少なくとも当方環境では。
引用返信 編集キー/
■81163 / inTopicNo.8)  Re[1]: Graphics.DrawLineでのオーバーフローについて
□投稿者/ 真田昌幸 (66回)-(2016/08/31(Wed) 11:13:14)
TCPポートの件は私の勘違いです。

No81145 (みくさわ さん) に返信
> いつもお世話になっております。
> 表記件について質問があります。
>
> 開発環境はVB2008です。
>
> Graphics.DrawLine(Pens.Red, Integer.MaxValue, 100, 1, 1)のコードを実行すると
> オーバーフローエラーが発生します。
> Integer.MaxValueの箇所を100とかにすると正常に動作することから、Integer.MaxValueで
> オーバーフローが発生しているのは間違いないのですが、DrawLineの引数はInteger型なのに
> 何故という疑問があります。

https://social.msdn.microsoft.com/Forums/ja-JP/f52184d9-8006-45f1-979d-6bd9fe5826a7?forum=csharpgeneralja

に内部的に16bitしか受け付けて無いかもと回答されてますね。

本当にそうなのかは、確かめてみるのがよいかと。

-1の件は、境界値付近が怪しいかもということで書きました。



引用返信 編集キー/
■81164 / inTopicNo.9)  Re[2]: Graphics.DrawLineでのオーバーフローについて
□投稿者/ 魔界の仮面弁士 (861回)-(2016/08/31(Wed) 11:32:10)
No81163 (真田昌幸 さん) に返信
> https://social.msdn.microsoft.com/Forums/ja-JP/f52184d9-8006-45f1-979d-6bd9fe5826a7?forum=csharpgeneralja
> に内部的に16bitしか受け付けて無いかもと回答されてますね。

…とは書かれていないように見えます。

「慣習的に、ウィンドウの座標、描画の座標は、short 型を超えない方がいいと思います」
という発言はありますけれどね。


> 本当にそうなのかは、確かめてみるのがよいかと。

少なくとも No81162 の実験コードでは、
Short.MinValue より小さな座標や
UShort.MaxValue より大きな座標への
DrawLine が呼び出せました。

Graphics.Clip の範囲を超えたとしても、必ずしもエラーになるわけでは無いようです。

ただし、極端に超えてしまうと、たとえエラーにならずとも
正しく描画されないケースもありましたので、運用上は
Clip (あるいはそれを多少超える程度) の範囲に留めて置くのが良さそうです。
引用返信 編集キー/
■81165 / inTopicNo.10)  Re[3]: Graphics.DrawLineでのオーバーフローについて
□投稿者/ 真田昌幸 (67回)-(2016/08/31(Wed) 12:00:17)
No81164 (魔界の仮面弁士 さん) に返信
> ■No81163 (真田昌幸 さん) に返信
>>https://social.msdn.microsoft.com/Forums/ja-JP/f52184d9-8006-45f1-979d-6bd9fe5826a7?forum=csharpgeneralja
>>に内部的に16bitしか受け付けて無いかもと回答されてますね。
>>本当にそうなのかは、確かめてみるのがよいかと。
>
> 少なくとも No81162 の実験コードでは、
> Short.MinValue より小さな座標や
> UShort.MaxValue より大きな座標への
> DrawLine が呼び出せました。
>
> Graphics.Clip の範囲を超えたとしても、必ずしもエラーになるわけでは無いようです。

なるほど。
質問者差し置いて、いろいろ書くのもなんですが、

>必ずしもエラーになるわけでは無いようです。

の部分が気になりますね。
本件と直接関係ないですが、GrapeCity社のSpredとかで、
定義最大桁の数値が勝手に丸まって切りあがる現象とかが起こったことがあるので、
(その場合の原因はおそらく2進10進問題なので今回とは原因が違う。おそらく。)
境界値近辺は端末の状態によって違うなんてことはあるかも
(根拠なし、想像)

> ただし、極端に超えてしまうと、たとえエラーにならずとも
> 正しく描画されないケースもありましたので、運用上は
> Clip (あるいはそれを多少超える程度) の範囲に留めて置くのが良さそうです。

そんな気はします。
質問者が仕様的にどうするか決める話ですが。

引用返信 編集キー/
■81170 / inTopicNo.11)  Re[2]: Graphics.DrawLineでのオーバーフローについて
□投稿者/ みくさわ (2回)-(2016/08/31(Wed) 12:35:24)
返信が遅れて申し訳ありませんでした。
また、皆様の回答、ありがとうございました。

今回はGraphics.Clipを最大値として、処理してみようと思います。

本当にありがとうございました。
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -