none
オーバーフローエラーについて RRS feed

  • 質問

  • お世話になります。

    以下の折れ線グラフを描画するプログラムで、オーバーフローエラーが発生します。

    Pen pen = new Pen(penColor, 1);

    Point[] arPt = new Point[lstGrhData.Count];
    for (int i = 0; i < lstGrhData.Count; i++)
    {

    // グラフデータを座標データに変換しています

         int x = (int)(Math.Round(ux * (lstGrhData[i].Time - ScaleXMin), MidpointRounding.AwayFromZero));
         int y = (int)(Math.Round((pnlGraph.Height - 1) - (uy * (lstGrhData[i].Data - ScaleYMin)), MidpointRounding.AwayFromZero));

         Point pt = new Point(x, y);

         arPt[i] = pt;

    }
    g.DrawLines(pen, arPt);

    arPt = null;
    pen.Dispose();

    エラー画面の詳細を確認すると、以下のような記述があります。

    System.OverflowException: オーバーフロー エラーです。

       場所 System.Drawing.Graphics.CheckErrorStatus(Int32 status)

       場所 System.Drawing.Graphics.DrawLines(Pen pen, Point[] points)

    ・・・

    上記のメッセージから、折れ線グラフを描画するときに使用している

    DrawLines関数でエラーが発生しているのはわかりました。

    質問1:何処が(どの変数が)オーバーフローしているのでしょうか?

    質問2:上記のオーバーフローエラーは、パソコンのOSの違いなどで、

        オーバーフローしたりしなかったりするものでしょうか?

        (客先で発生するオーバーフローエラーが私のパソコンで再現できません。)

    以上の2点についてご教示ください。

    よろしくお願いいたします。


    2013年4月25日 11:26

回答

  • .NET は内部で GDI+ というコンポーネントを使っています。
    GDI+ は、Windows のバージョンによって搭載されているバージョンが異なるので、あるバージョンの Windows で再現し、別のバージョンの Windows では再現しないことは起こりえます。
    (個人的には、GDI+ のエラーはあまり当てにならないと思っています。正しいエラー原因を示しているとは限らないためです。)

    例外が発生するときの座標群をログに書き出すようなものを用意してユーザーに再現協力を求めるとともに、発生する OS を特定して試してみるところでしょうか。
    特定できたとして、極端な座標群を渡さない、DrawLines ではなく DrawLine で回避するということになりそうですが…。

    • 回答の候補に設定 星 睦美 2013年4月26日 0:43
    • 回答としてマーク エネコン 2013年5月2日 2:36
    2013年4月25日 14:14
    モデレータ
  • Azuleanさんも「個人的には、GDI+ のエラーはあまり当てにならない」と書かれているように、オーバーフローしたというエラーそのものが当てにならず、そもそもどんなエラーが発生しているのかわからないです。もしかするとオーバーフローしているのかもしれませんが。
    • 回答としてマーク エネコン 2013年5月2日 2:36
    2013年4月26日 6:13
  • DrawLinesで描画できるPointに上下限があるようですが、上下限値はどのように決まるのでしょうか?

    実装によって決まります。
    このあたりは仕様として明言されていないので、確実な情報を得ることはできません。最悪の場合、OS 依存で変わっている可能性もあります。

     Pointのx・yは、int型なので、int型で表現できる値であれば、 問題ないと思っていたのですが...

    慣習的に、ウィンドウの座標、描画の座標は、short 型を超えない方がいいと思います。
    どこかしらに昔の制限が残っていることもあるので。

    • 回答としてマーク エネコン 2013年5月2日 2:36
    2013年4月26日 16:57
    モデレータ

すべての返信

  • .NET は内部で GDI+ というコンポーネントを使っています。
    GDI+ は、Windows のバージョンによって搭載されているバージョンが異なるので、あるバージョンの Windows で再現し、別のバージョンの Windows では再現しないことは起こりえます。
    (個人的には、GDI+ のエラーはあまり当てにならないと思っています。正しいエラー原因を示しているとは限らないためです。)

    例外が発生するときの座標群をログに書き出すようなものを用意してユーザーに再現協力を求めるとともに、発生する OS を特定して試してみるところでしょうか。
    特定できたとして、極端な座標群を渡さない、DrawLines ではなく DrawLine で回避するということになりそうですが…。

    • 回答の候補に設定 星 睦美 2013年4月26日 0:43
    • 回答としてマーク エネコン 2013年5月2日 2:36
    2013年4月25日 14:14
    モデレータ
  • 回答ありがとうございます。

    アドバイスいただいた通り、ユーザーに再現協力いただこうと思います。

    質問1:

    >DrawLines ではなく DrawLine で回避するということになりそうですが…。

     極端な座標群でもDrawLine にするとエラーが発生しなくなるということでしょうか?

    質問2:

    オーバーフローをしているのはDrawLinesに渡している座標群(arPt)

    ということでよかったでしょうか?


    2013年4月26日 0:32
  • Azuleanさんも「個人的には、GDI+ のエラーはあまり当てにならない」と書かれているように、オーバーフローしたというエラーそのものが当てにならず、そもそもどんなエラーが発生しているのかわからないです。もしかするとオーバーフローしているのかもしれませんが。
    • 回答としてマーク エネコン 2013年5月2日 2:36
    2013年4月26日 6:13
  • 回答ありがとうございます。

    >「個人的には、GDI+ のエラーはあまり当てにならない」

    すいません。オーバーフローしているか否かわからないということですね。

    ご指摘ありがとうございます。

    なお、DrawLinesにint型で表現できる最大の値(Point)を渡したら、

    オーバーフローすることがわかりました。

    DrawLinesで描画できるPointに上下限があるようですが、

    上下限値はどのように決まるのでしょうか?

     Pointのx・yは、int型なので、int型で表現できる値であれば、

     問題ないと思っていたのですが...

    よろしくお願いいたします。

    2013年4月26日 9:14
  • DrawLinesで描画できるPointに上下限があるようですが、上下限値はどのように決まるのでしょうか?

    実装によって決まります。
    このあたりは仕様として明言されていないので、確実な情報を得ることはできません。最悪の場合、OS 依存で変わっている可能性もあります。

     Pointのx・yは、int型なので、int型で表現できる値であれば、 問題ないと思っていたのですが...

    慣習的に、ウィンドウの座標、描画の座標は、short 型を超えない方がいいと思います。
    どこかしらに昔の制限が残っていることもあるので。

    • 回答としてマーク エネコン 2013年5月2日 2:36
    2013年4月26日 16:57
    モデレータ
  • 回答ありがとうございます。

    >慣習的に、ウィンドウの座標、描画の座標は、short 型を超えない方がいいと思います。

    参考になりました。

    DrawLines関数を実行する前に座標データをチェックするようにします。

    あと、最初の質問で、

    「客先で発生するオーバーフローエラーが私のパソコンで再現できません」

    と記載しましたが、勘違いでした。

    失礼しました。

    みなさんの回答、大変参考になりました。

    ありがとうございます。

    2013年5月2日 2:35