配列のサイズと量について


fab  2012-08-13 08:48:42  No: 42752

delphiでは配列のサイズは2GBまでと言われておりますが、配列の量にも許容値は存在するのでしょうか?(無限だとは思っておりませんが。)

というのはかなり大きなサイズの静的配列をいくつか用意し、そのうちの1つの配列に数値を代入しようとするとEAccessViolationの例外が発生してしまい、代入できない状態となっております。

メモリを確保してある事は確かで、そのメモリにアクセスしている事も確認済みです。

どなたかお詳しい方にご教授頂けますと幸いです。


Mr.XRAY  2012-08-16 19:43:49  No: 42753

こんにちは,Mr.XRAYです.

配列への数値の代入ということですが,
この文章だと,おそらく,多くの方がレスに困ってしまうと思います.
レスする方は,たいてい,具体的な解決策を考えるものです.

配列になにを使用しているのか?
その配列をどのように定義しているのか?
その配列にどのように代入していのか?

という情報があれば,あるいは,レスがつくかも知れません(保証はありませんが).
また,Delphiのバージョンによっては,デバック時に配列のチェックの状態を
報告してくれるものもあります.

参考までに(また嫌われてしまうな...).
[現在トラブルを抱えています。"(コミュニティ名)" で素早く回答を得るにはどうすればいいのでしょうか?]
http://ht-deko.minim.ne.jp/tech045.html#tech095


Quest  2012-08-16 21:29:29  No: 42754

試しにDelphi2007でやってみました。

  Array1: array [1..64, 1..1024, 1..1024] of double; //512MB
  Array2: array [1..64, 1..1024, 1..1024] of double; //512MB
  Array3: array [1..64, 1..1024, 1..1024] of double; //512MB
  Array4: array [1..64, 1..1024, 1..1024] of double; //512MB

このような配列をクラスの中に宣言したら、コンパイル時にエラーになりました。
クラスの外で宣言するとコンパイルは出来ますが、実行すると起動できずに
access violation になりました。
それじゃってんで、Array4を減らしてみると
  Array4: array [1..43, 1..1024, 1..1024] of double; //344MB
が実行できる限界でした。
もちろん、実行する環境などに左右されると思いますし、細かく詰めれば
もうちょっとメモリを確保できると思いますが、基本的に32ビット
アプリケーションでは、1つのプロセスで使用できるメモリは2GBまで
ということだと思います。
ですので、2GBからアプリ自体のフォームなどで使用する分などを除いたものが
確保できる変数領域ということでしょう。

どうしても2GB以上同時に必要ならば、64ビットに移行するしかないのでは?
(XE2で、64ビットで試そうとしたら、実行環境がなかった^^;)


Mr.XRAY  2012-08-16 23:26:18  No: 42755

Quest さん,どうもです.
すごい配列ですね!!

>(XE2で、64ビットで試そうとしたら、実行環境がなかった^^;)

やってみました.

[DCC エラー] Unit1.pas(16): E2100 型が大きすぎます : 2 GB を超えました

となりました.コードは以下です.
Array4 をなくすとエラーはでませんでした.
Windows 7 U64 + Delphi XE2(UP4) VCL-64

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
  private
    { Private 宣言 }
    Array1: array [1..64, 1..1024, 1..1024] of double; //512MB
    Array2: array [1..64, 1..1024, 1..1024] of double; //512MB
    Array3: array [1..64, 1..1024, 1..1024] of double; //512MB
    Array4: array [1..64, 1..1024, 1..1024] of double; //512MB
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

end.


Quest  2012-08-17 00:05:52  No: 42756

Mr.XRAYさん、どもです。

64ビットでも1つのインスタンスは2GBまでなんでしょうかね?
下記のようにしたら、実行できますか?
Delphi2007ではコンパイルは通りますが、実行時にエラーになります。

type
  TForm1 = class(TForm)
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;
  Array1: array [1..64, 1..1024, 1..1024] of double; //512MB
  Array2: array [1..64, 1..1024, 1..1024] of double; //512MB
  Array3: array [1..64, 1..1024, 1..1024] of double; //512MB
  Array4: array [1..64, 1..1024, 1..1024] of double; //512MB

implementation

{$R *.dfm}

end.


Mr.XRAY  2012-08-17 00:31:53  No: 42757

どうもです.
失礼しました.

>下記のようにしたら、実行できますか?

こちらのテストもあったんですね.
こちらはエラーはなにも現れませんです.

>64ビットでも1つのインスタンスは2GBまでなんでしょうかね?

そんな感じですね.もしかしてたら設定があるのかも知れませんが.
何かレコード型で定義して,それを使用するというやり方があるかも知れません.
何か,配列ではありませんでしたが,そんなやり方をしたことがあります.


Mr.XRAY  2012-08-17 00:33:39  No: 42758

しかし,こんなどでかい配列,わたしゃ使いません.キッパリ !! (笑)


Mr.XRAY  2012-08-17 01:04:32  No: 42759

一応代入と取り出しテストコードです.
代入も取り出しもできているようです.

procedure TForm1.Button1Click(Sender: TObject);
var
  ASize : Int64;
  D     : Double;
  S     : String;
begin
  ASize := SizeOf(Array4);
  ShowMessage(IntToStr(ASize)); //536870912

  Array4[64, 1024, 1024] := 100.123;
  D := Array4[64, 1024, 1024];
  S := FormatFloat('###,##0.000', D);
  ShowMessage(S);

  Array2[60, 1000, 1000] := 213.515;
  D := Array2[60, 1000, 1000];
  S := FormatFloat('###,##0.000', D);
  ShowMessage(S);
end;


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加