UNITを追加したら、読み取り違反のエラーが出るようになったのですが??

解決


AS  2018-08-23 05:08:46  No: 49383

UNIT1とUNIT2ならなるプログラムがあり、問題なく動いていました。
パスワードを確認するプログラムUnit3を組み込んだら、
UNIT1で
「モジュール'AAA.exe'のアドレス0040B713deアドレスFFFFFFFFBに対する
読み取り土地違反が起きました。」
というエラーが出るようになりました。

UNIT3の中の変数宣言の中の文字変数が原因でした。
下のようなUnit3を作ってコンパイルしても、
STRをstringにしたらエラーが出て、integerにしたらエラーは出ません。

なぜこうなるのか、教えてもらえませんか??

unit Unit3;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

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

var
  Form3: TForm3;
  STR:integer; //;string;
implementation

{$R *.dfm}


Mr.XRAY  2018-08-23 08:06:49  No: 49384

var 
  STR:integer;
  
とすると,変数 STR には Integer 型の値しか代入できません.   
  
var 
  STR:string;   
  
とすると,変数 STR には string 型の値しか代入できません.   

そういうこではないのですか ?

# 優れたプログラマは真似る
# 偉大なプログラマは盗む


igy  2018-08-23 08:45:47  No: 49385

判断するのに必要な情報がほとんどないので、断定できませんが、

> UNIT3の中の変数宣言の中の文字変数が原因でした。 

実際は、これが原因では、ないかもしれませんね。

> パスワードを確認するプログラムUnit3を組み込んだら、

と書かれているのに、

>  TForm3 = class(TForm) 
>  private 
>    { Private 宣言 } 
>  public 
>    { Public 宣言 } 
>  end; 

それらしきものが一切ないのも謎ですし・・


Mr.XRAY  2018-08-23 08:53:51  No: 49386

変数 STR はグローバル変数になっていますから,それも要チェックですね.
( 別のユニット等でも同じ STR の定義があるとか)


igy  2018-08-23 09:23:00  No: 49387

> 判断するのに必要な情報がほとんどないので、

フォームの生成方法が自動生成なのか、コード上で生成しているのか、
もし自動生成の場合、UNIT1とUNIT3では、生成の順番がどのようになっているのか、
エラーが出るタイミングは、いつ出るのか、
UNIT3は、UNIT1のどのイベント(FormCreateとか?)で、表示しているのか・・あたりも気になりますね。


AS  2018-08-23 15:08:29  No: 49388

Mr-XRAYさん、igyさん、ありがとうございます。

単純にstring変数を宣言するだけでもエラーが出るんです
と言いたいために、簡単なunit3を記載しました。

実際には、ここで質問した後、無理やり解決しました。

UNIT3で宣言しているstring型変数1個を消してUNIT1で宣言している変数を使用すること、
UNIT3のstring型1個、integer型1個をProcedure内で宣言すること、
これで正常に動くようになりましたが、確認するために、
エラーが起きるようにもとに戻し、さらにエラーが起きないようにしたら、
まだエラーが出ました。

最後にUNIT1で使っている、VBで作成した英語と日本を話すプログラムを
使うProcedure2個を使用しないようにしたら、正常に動くように
なりました。

なんか、変数領域の限界まで使っているのではと思うんですが、
そんなことはありませんか??

ただし、UNIT3をメインプログラムにしてパスワードを確認してから、
UNIT1を呼び出すプログラムは正常に作動しています。


AS  2018-08-23 15:32:15  No: 49389

igyさん
>フォームの生成方法が自動生成なのか、コード上で生成しているのか、 
意味がちょっと分かりません。

>もし自動生成の場合、UNIT1とUNIT3では、生成の順番がどのようになっているのか、 
UNIT1からUNIT3を呼び出しています。

>エラーが出るタイミングは、いつ出るのか、 
> UNIT3は、UNIT1のどのイベント(FormCreateとか?)で、表示しているのか・・あたりも気になりますね。
UNIT1のFormCreateで使っていますが、FormActivateで呼び出してもエラーが
出ることは変わりませんでした。


AS  2018-08-23 15:46:17  No: 49390

Mr-XRAYさん

>変数 STR はグローバル変数になっていますから,それも要チェックですね. 
>( 別のユニット等でも同じ STR の定義があるとか)
もちろん、確認済です。

以前の質問で、XRAYさんの指摘されたことをメモしておきますと言ってましたが、
代わりに使ったプログラムで別のwin10のパソコンで文字化けが起こり、
正式採用に復帰したことを、感謝の気持ちを添えて、ご報告させていただきます。

ありがとうございました。


Mr.XRAY  2018-08-23 17:37:50  No: 49391

>UNIT3で宣言しているstring型変数1個を消してUNIT1で宣言している変数を使用すること、 
>UNIT3のstring型1個、integer型1個をProcedure内で宣言すること、 
>これで正常に動くようになりましたが、 

そういうことだと思いますよ.
でも,この書き方では,この文章を読んでいる人には理解できません.
変数名が書いてありません.宣言の場所も書いてありません.

# 優れたプログラマは真似る 

他の方のレスの仕方も真似ることです.

interface 部 (implementation よりも上) に以下のように定義した変数はグローバルです.
他のユニットからも直接参照できます.Form3 がそうであるように.
したがって,この同じ変数名を,別のユニットでこのように定義すると混乱の元となります.

var 
  Form3: TForm3; 
  STR:integer; //;string; 
  
以下のように implementation 部以降で定義した変数も,グローバル変数ですが,  
このユニット内だけ ( implementation 以降だけ) のグローバル変数です.
しかし,これも,他のユニットの interface 部で同じ変数名を定義していると,
混乱の原因となります.
グローバル変数の変数名には注意が必要です.

implementation 
  STR:integer; //;string; 

Procedure 内で宣言した変数はその Procedure 内だけで有効 (参照可能) です.
同じ変数名のグロバール変数があっても Procedure 内で定義した変数名が優先して使用されます.


Mr.XRAY  2018-08-23 17:39:27  No: 49392

implementation 
  STR:integer; //;string; 
          ↓
implementation 
var
  STR:integer; //;string;


Mr.XRAY  2018-08-23 18:49:46  No: 49393

ちなみに str というのは同名の関数があります.
可能であれば変数名に使わない方が無難かも知れません
( Delphi は,変数名や関数名の大文字と小文字を区別しません)

http://docwiki.embarcadero.com/Libraries/Tokyo/ja/System.Str


AS  2018-08-24 08:39:45  No: 49394

Mr-XRAYさん、ありがとうございます。

implementation の下で宣言した変数がUNIT内だけのグローバル変数ということは、
初めて知りました。
usesの下で宣言しないといけないようですね。
ただ、やはり、Integerならエラーは出ませんが、Stringならエラーが出ます。

implementation 
uses  UNIT1,UNIT2;
var   ASTR:integer; //;string; 

integerとStringの違いは宣言した時に確保されるバイト数だと思うので、
どうしても、変数領域の範囲を超えてるのではと思うんですが??

そういうことはありませんか??

このパスワード確認ようのUNIT3は単独で使用できるようにしようと思っていますので、
UNIT1で宣言された変数を使くことは避けたいと思っています。


AS  2018-08-24 11:26:35  No: 49395

UNIT3で使っている文字変数の宣言を、stringではなくshortstringに変えたら、
問題はおこらなくなりました。

原因は、変数領域?のほとんどすべてを使っているからだと思うことにします。

ありがとうございました。


通りすがり  2018-08-24 15:51:26  No: 49396

ShortStringはやめて…
というかこれで解決したと思うのは、本当にあり得ないので。

例外が発生してデバッガに制御が移ったときに、どのような処理で止まりますか?
それはUnit1、Unit2、Unit3のどのユニットですか?例外が発生して表示される行の直前の
処理が大体原因なのですが、そのあたりにブレークポイントをかけて、1行ずつ実行して
みたら何かわかりませんか?


通りすがり  2018-08-24 15:55:59  No: 49397

あと、

> なんか、変数領域の限界まで使っているのではと思うんですが、 
> そんなことはありませんか?? 

> 原因は、変数領域?のほとんどすべてを使っているからだと思うことにします。 

絶対に違います。何か思い込みが激しいようですが、原因はあなたのコードにあります。
おそらく原因はグローバル変数領域のバッファオーバフローです。何らかの原因で
Form3(これはポインタ型)の次に配置されている変数に別の内容を上書きしてしまっています。


Mr.XRAY  2018-08-24 18:10:27  No: 49398

確かに以前から思い込みが非常に激しいようですね (笑).

他のユニットで使いたい変数は,一般的には public 部で定義します.
public 部で定義すると,定義したユニット名やフォーム名を付けて,
Form3.STR 等のようにしないと他のユニットからは使用できませんから,
トラブル発生の防止になります.

以下のような場所で定義するのは特別な場合です.
例えばフックのコールバック関数内で取得した値を処理する場合等です.

var 
  Form3: TForm3; 
  STR:integer; //;string; 
[ 参考 ]
http://mrxray.on.coocan.jp/Delphi/plSamples/122_PluralForms.htm#list13


AS  2018-08-25 18:37:15  No: 49399

通りすがりさん、ありがとうございます。

UNIT3で宣言した変数は、全然使っていないのですよ。
コンパイルも、起動もします。
そして確かにエラーを起こす部分以外では正常に作動します。

shortstringは、UNIT1のstring型の配列変数の量を減らしたので、
integerに戻しても正常に作動しました。

>おそらく原因はグローバル変数領域のバッファオーバフローです。
まあ、私の言いたいこともこういうことなんだと思いますが、
バッファオーバフローの意味を正しく知っているとは言えません。
integer、shorstringをstringにしたらオーバーフローするという
仕組みを少し解説してもらえませんか??

もうひとつ、stringを宣言したらコンパイルされたプログラム内で
何バイト変数領域を確保されるのですか??

Mr.XRAYさん
PUBLICってなんだあとか思ってしまいました。
いままで、全然使っていませんでした。
私としては、いちいちUNIT名をつけるのはしんどいので、
使いたくはないですが。

unit内だけのグローバル変数を
implementation
uses UNIT1,UNIT2;
var  DrtPath:string;
     WindowsID:integer;
のように宣言できることを教えてもらったことはうれしいです。
紹介されたHPは後で読まさせていただきます。

もうひとつ質問させてください。
ボタンを25個使ったUNIT1だけの電卓を作っていますが、これのサイズが10,507KBです。
今問題になっているUNITを3つ使ったプログラムが10,709KBです。
そして60unitくらいのプログラムが7,606KBsです。
この違いはどうして生じるのでしょうか??

8bitマシーンのころは変数に気を使っていましたが、
32bit、64bitでこういうことは初めてです。


通りすがり  2018-08-25 19:55:15  No: 49400

> shortstringは、UNIT1のstring型の配列変数の量を減らしたので、 
> integerに戻しても正常に作動しました。 
これ原因じゃないですかね?Unit1の持つ配列に対して、例えば10要素ある配列で[10]とか[11]にアクセスしてませんか?
プロジェクトオプションのDelphiコンパイラのコンパイルにある実行時エラーのオーバーフローチェックと
範囲チェックにチェックオンして実行するとエラーで例外がでませんか?

> integer、shorstringをstringにしたらオーバーフローするという 
> 仕組みを少し解説してもらえませんか?? 
じゃなくてオーバランでこれらの領域を踏み潰している(↑のように)ということです。String型は
裏でいろんな仕組みが働く型なので、その仕組みが異常を

> PUBLICってなんだあとか思ってしまいました。 
> いままで、全然使っていませんでした。 
Delphi を使ったプログラミング:インデックス - RAD Studio
http://docwiki.embarcadero.com/RADStudio/Tokyo/ja/Delphi_%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%EF%BC%9A%E3%82%A4%E3%83%B3%E3%83%87%E3%83%83%E3%82%AF%E3%82%B9

あたりを一通りさらっと読んでみてはいかがですか?DelphiはObject Pascalという言語の上に成り立っていて、
Object Pascalという言語はオブジェクト指向という考え方に沿って作られているので、ここからあまり
離れてしまっていると、質問をしても回答しようとしている人との意思疎通がうまくいかないのかと。

> もうひとつ、stringを宣言したらコンパイルされたプログラム内で 
> 何バイト変数領域を確保されるのですか?? 
String型はポインタなので4バイトです(その他に文字列を格納する領域が別途取られます)。

> ボタンを25個使ったUNIT1だけの電卓を作っていますが、これのサイズが10,507KBです。 
> 今問題になっているUNITを3つ使ったプログラムが10,709KBです。 
> そして60unitくらいのプログラムが7,606KBsです。 
実行ファイルのサイズはプログラムに含まれるコードとデータ、それにデバッグ情報の合計で決まりますが、
ボタンなどのコントロールはいくつあってもコードは基本的に同じ量です。つまりプログラムの実行ファイルの
サイズはほぼあなたの書いたコードの量+プロジェクトオプションで指定したデバッグ情報の設定で決まります。
ちなみに実行時にメモリ上に取られるサイズはまた別の話です。


通りすがり  2018-08-25 19:58:55  No: 49401

あー、なんか中途半端な書き込みになってしまいました。

> じゃなくてオーバランでこれらの領域を踏み潰している(↑のように)ということです。String型は 
>裏でいろんな仕組みが働く型なので、その仕組みが異常を 
検知してエラーになっている(Integerはそのような仕組みがなく、ShortStringはまた違う仕組み)と
いうことです。


通りすがり  2018-08-25 20:02:18  No: 49402

連投になりますが、

> そして確かにエラーを起こす部分以外では正常に作動します。 

そうではなくて、

> 例外が発生してデバッガに制御が移ったときに、どのような処理で止まりますか? 
> それはUnit1、Unit2、Unit3のどのユニットですか?例外が発生して表示される行の直前の 
> 処理が大体原因なのですが、そのあたりにブレークポイントをかけて、1行ずつ実行して 
> みたら何かわかりませんか? 

は答えてもらえませんか?


AAA  2018-08-25 21:10:11  No: 49403

>STRをstringにしたらエラーが出て、integerにしたらエラーは出ません。 
エラーが出ないというか、コンパイラーが通らないだろふつう
型が違うって。。出ないって事は使っていない?

もしくは

var
  P: Pointer;
  STR: String;
begin
  P := @STR;

var
  V: Variant;
begin
  V := STR;

みないたことしてたら String だろうが Integer だろうがコンパイルは通るけど

STR:String を STRXXX: String にしてエラーが出るなら DELPHI 側のバグかも
STRXXX  は使用していない適当な名前


Mr.XRAY  2018-08-26 02:03:56  No: 49404

今回のこの現象はハッキリさせた方がいいと思いますよ.
この掲示板は多くの方が観ています.誤解を招く恐れがあります.
今回のこの現象は,通常では考えられない現象です.

var 
  Form3: TForm3; 
  STR:integer; //;string; 
  
AS さんはこの部分以外に STR と言う変数には一切触れていません.  
と言うことは,他で STR という変数を使っていないと解釈すると,

> STRをstringにしたらエラーが出て、integerにしたらエラーは出ません。 

と言うエラーが発生するハズがありません.
とすると,それは Delphi のバグということになってしまいます.
AS さんはそう言いたげな雰囲気のようです.
私が使っている Delphi では発生しませんが.


AS  2018-08-26 04:02:18  No: 49405

AAAさん、一番最初に示しているSTRはUNIT,UNIT2,UNIT3どこでも使用していません。
よって、コンパイルはできるんです。

STRをstringにすると、UNIT1でエラーが出るんです。


AS  2018-08-26 04:28:17  No: 49406

通りすがりさん

いろいろ書いてもらって、ありがとうございます。
4バイトというのは、場所だけ指定するんでしょうね??

場所を特定するという作業は、プログラムを変更していますので、
元に戻してまでは、できません。また、integerにしたらエラーは出ないし、
UNIT3を入れるまでは、エラーは起こっていなかったので、プログラムミスは
ないと思っています。
変数領域が大きすぎたのが原因だと思います。

サイズの話ですが、電卓のプログラムなんてものすごく単純ですよね?
それが何で60UNITの膨大な、自分でもよくわからなくなるようなプログラムの
サイズのほうが少ないのか、お聞きしたいのですが??


AS  2018-08-26 04:57:41  No: 49407

Mr.XRAYさん

>> STRをstringにしたらエラーが出て、integerにしたらエラーは出ません。 

>と言うエラーが発生するハズがありません. 
>とすると,それは Delphi のバグということになってしまいます. 

最初は私もdelphiのバグかなとか思いましたが、
integer型のバイト数とstring型のバイト数の違いを考え、
変数の量が多すぎて限界を超えてるんだと考えたら、納得できました。

実際、配列変数の量を1/4にしましたが、エラーは出なくなりましたよ。

ネットで調べていたら、string変数には最大10億文字が入るとかありました。
実際に、配列変数を大きくとってデータを入れていって、どのあたりが限界か
調べた見たらいいのではないでしょうか??

それから、HP見ました。昔delphiに移行した時には、private、publicも読んだなあ
と思い出しましたが、プログラム始めると
type 
   TForm3 = class(TForm) 
   private 
     { Private 宣言 } 
   public 
     { Public 宣言 } 
   end; 

 var 
   Form3: TForm3; 
   STR:integer; //;string; 
 implementation 

この部分のVarに記入してしまっていました。
usesでUNITを指定して使い分けると不便はなく、さすがにdelphiと思って、使い続けています。
さすがにこれからはPrivateは使おうと思いますが。

問題になっているこのプログラムも、音声を理由にVBで作ろうかとしましたが、
ボタンを8個配置したら、わけのわからないコードが突然現れて、
早々にあきらめました。

ボタンを25個使った電卓プログラムのサイズが、68のUNITを使ったプログラムのサイズより
大きくなるのか、教えてもらえませんか??


Mr.XRAY  2018-08-26 05:16:55  No: 49408

> 68のUNITを使ったプログラムのサイズより大きくなるのか、教えてもらえませんか?? 

思い込みが激しいようですので,説明しても受け入れてくれそうもないようです.
ですので以下の 2 つのプログラムをコンパイルして EXE のサイズを
比べて見てください.
それで何故かを自分の「思い込み」で判断してください.

program Project1;

uses
  Winapi.Windows,
  System.SysUtils;

begin
  MessageBox(0, 'Exit', 'Exit', MB_ICONINFORMATION);
end.

program Project2;

uses
  Winapi.Windows,
  System.SysUtils,
  Vcl.Forms;

begin
  MessageBox(0, 'Exit', 'Exit', MB_ICONINFORMATION);
end.


igy  2018-08-26 05:20:28  No: 49409

> 実際、配列変数の量を1/4にしましたが、エラーは出なくなりましたよ。 

最初の質問では、配列変数に関しては、一切触れられていないみたいですが、
その配列変数を含む、エラーを再現できるコードをここに挙げてみるのは、いかがですか?
(他の人が検証できるように、新規プロジェクトから作成して、エラーが出るコードを)


通りすがり  2018-08-26 05:27:24  No: 49410

自分の空想に浸るのは公開の場ではやめましょう。

> STRをstringにすると、UNIT1でエラーが出るんです。 

> > 例外が発生してデバッガに制御が移ったときに、どのような処理で止まりますか? 
> > それはUnit1、Unit2、Unit3のどのユニットですか?例外が発生して表示される行の直前の 
> > 処理が大体原因なのですが、そのあたりにブレークポイントをかけて、1行ずつ実行して 
> > みたら何かわかりませんか? 

> は答えてもらえませんか? 

> プロジェクトオプションのDelphiコンパイラのコンパイルにある実行時エラーのオーバーフローチェックと 
> 範囲チェックにチェックオンして実行するとエラーで例外がでませんか? 

プログラムサイズの話はいい質問だとは思いますが、とっちらかってしまうので別に質問されたら
いかがですか?ファイルサイズの話、実行時にメモリにメモリサイズの話、いろいろありますので。

あとエラーが発生したときは、それがコンパイル時なのか実行時なのかをはっきり書いてください。
またそのときのエラーメッセージはコピペで1文字の間違いもなく提示してください。
コンパイル時ならIDEに表示されているエラーメッセージを選択して右クリック→コピーで、
実行時ならエラーダイアログでCtrl+Cでクリップボードにコピーできます。


AAA  2018-08-26 06:05:42  No: 49411

どっかでメモリ確保し忘れて(もしくは足りない)
そのメモリにアクセスしにいって
そのアドレスが変数で確保してるメモリとかぶってる
かな?


Mr.XRAY  2018-08-26 07:07:33  No: 49412

>どっかでメモリ確保し忘れて(もしくは足りない) 
    (以下,略)
    
配列という新たな登場がありましたからね.
そもそも 

『モジュール Project1.exe のアドレス〇〇でアドレス〇〇に 対する読み込み (書き込み) 違反がおきました。』

というエラーはメモリのアクセス違反のエラーですからね.

(1) 解放済みのメモリにアクセスしようとした
(2) 確保していないメモリにアクセスしようとした
(3) 作成されていないオブジェクトに何かしようとした
(4) 解放済みのオブジェクトに何かしようとした
(5) 生成していなフォームの何かにアクセスした

等々ですよね.
配列のサイズを 1/4 にしたら例外 (?) が発生しなくなったと書いていますが,
配列のサイズの問題だとすると String 型の定義で例外が発生して,
Integer 型と ShortString 型だと例外が発生しない説明が付きません.
String 型よりも ShortString 型の方が定義した初期段階ではメモリを使いますから.

# 配列のサイズが原因だと別の例外かエラーなるのでは...


通りすがり  2018-08-26 09:15:00  No: 49413

String型はmanagedなので、その変数領域(文字列保持領域ではなく)を踏み潰すとPODな型と違って
メモリマネージャかRTLがエラります。
(ShortStringはarray [0..255] of AnsiCharですからmanagedではない)


Mr.XRAY  2018-08-26 09:26:10  No: 49414

>String型はmanagedなので、その変数領域(文字列保持領域ではなく)を踏み潰すとPODな型と違って 
>メモリマネージャかRTLがエラります。 

そうですか.なるほど.
ところで,似たようなエラーは,例えば次のようなコードでも発生させることができます.
今回と関係あるかは疑問ですが.

procedure TForm1.Button1Click(Sender: TObject);
var
  LStr   : string;
  LChar  : Char;
  LIndex : Integer;
begin
  LIndex := 0;
  LChar  := LStr[LIndex];
end;

モジュール 'Project1.exe' のアドレス 005B8EC6 でアドレス FFFFFFFE に対する読み取り違反がおきました。.


通りすがり  2018-08-26 09:32:25  No: 49415

あてずっぽうではあるのですが、Unit2のinterface部のForm2: TForm2;の次に何らかの配列変数があって、
この配列への書き込みでオーバランしてForm3や次のStrを踏み抜いているんじゃないかと想像してます。
え、減らしたらエラーが出ない?もっと後ろを踏み抜いたけど顕在化してないだけじゃないですか?


Mr.XRAY  2018-08-26 16:32:45  No: 49416

>この配列への書き込みでオーバランしてForm3
  (以下,略)

かも知れませんね.
例えば以下のコードを実行します.
プロジェクトのオプションの [範囲チェック] が false だとエラーは発生しません.
つまり配列の範囲外にアクセスしても気が付かないことがあります.

プロジェクトのオプションの [範囲チェック] を true にして,
プロジェクトを [ビルド] (再構築) すると,

『範囲チェックエラー.』

となります.

procedure TForm1.Button1Click(Sender: TObject);
var
  LStrArray : array of string;
  LStr      : string;
  Lindex    : Integer;
begin
  SetLength(LStrArray, 25);
  Lindex := 100;
  LStr   := LStrArray[Lindex];
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  LStrArray : array of string;
  Lindex    : Integer;
begin
  SetLength(LStrArray, 25);
  Lindex := 100;
  LStrArray[Lindex] := 'ABC';
end;


Mr.XRAY  2018-08-26 16:58:07  No: 49417

>プロジェクトを [ビルド] (再構築) すると, 

プロジェクトを [ビルド] (再構築) してから実行すると,ですね.
動作確認は Windows 7 U64(SP1) + Delphi XE5(UP2) Pro VCL-32 です.


Mr.XRAY  2018-08-26 17:28:36  No: 49418

> この配列への書き込みでオーバランしてForm3や次のStrを踏み抜いているんじゃないかと想像してます。 

これで Integer, ShortString 型だと例外が発生しないのが理解できますね.
Integer 型も ShortString 型も変数を定義した段階で領域が確保されますから.


AS  2018-08-27 01:47:26  No: 49419

Delphiの限界を試すプログラムを作って、自分の配列より大きくしても、
エラーは出ませんでした。で、もう一度、エラーの出るプログラムを再現してみました。

最初に示したUNIT3を使って、確認しました。
コンパイルは正常にすべてできます。エラーはすべて同じ場所で起こります。
4個の選択肢表示する部分で起こります。変数が範囲を超えているんだと思います。
(1)UNIT1の配列変数を減らしてもエラーは消えません。
(2)STRA:string;をpriveteで宣言するとエラーは消えます。
(3)implementationの下においてもエラーは消えません。
(4)STR:integer;にするとエラーは消えます。

変数の個数を減らしたら直ったというのその時だけだったようです。
いろいろほかの部分も変更したので、現在は問題ありません。

UNIT2のことでは、ボタンが9個ラベルが9個あるだけですから、問題ではありません。

UNIT1,UNIT2だけでコンパイルすると、何も問題はないので、UNIT1やUNIT2について
考えても無駄だと思っていますが、また今後万一何か異常が出たら考えてみたいと思います。


AS  2018-08-27 02:01:23  No: 49420

1個のボタンだけのFormをコンパイルすると、10531KBの大きさがありました。
まあ、こういうことなんだと思っておくことにしました。

大きさに関する質問は取り消します。


通りすがり  2018-08-27 02:32:14  No: 49421

> STRをstringにすると、UNIT1でエラーが出るんです。 

> 例外が発生してデバッガに制御が移ったときに、どのような処理で止まりますか? 
> それはUnit1、Unit2、Unit3のどのユニットですか?例外が発生して表示される行の直前の 
> 処理が大体原因なのですが、そのあたりにブレークポイントをかけて、1行ずつ実行して 
> みたら何かわかりませんか? 

> プロジェクトオプションのDelphiコンパイラのコンパイルにある実行時エラーのオーバーフローチェックと 
> 範囲チェックにチェックオンして実行するとエラーで例外がでませんか? 

> あとエラーが発生したときは、それがコンパイル時なのか実行時なのかをはっきり書いてください。 
> またそのときのエラーメッセージはコピペで1文字の間違いもなく提示してください。 
> コンパイル時ならIDEに表示されているエラーメッセージを選択して右クリック→コピーで、 
> 実行時ならエラーダイアログでCtrl+Cでクリップボードにコピーできます。


igy  2018-08-27 04:45:27  No: 49422

> で、もう一度、エラーの出るプログラムを再現してみました。 

> 最初に示したUNIT3を使って、確認しました。 
> コンパイルは正常にすべてできます。エラーはすべて同じ場所で起こります。 
> 4個の選択肢表示する部分で起こります。変数が範囲を超えているんだと思います。 
> (1)UNIT1の配列変数を減らしてもエラーは消えません。 
> (2)STRA:string;をpriveteで宣言するとエラーは消えます。 
> (3)implementationの下においてもエラーは消えません。 
> (4)STR:integer;にするとエラーは消えます。 

他の人が検証できるように、このソースコードを、ここに挙げてみるのは、いかがですか?


Mr.XRAY  2018-08-27 08:16:15  No: 49423

> 4個の選択肢表示する部分で起こります。

と書かれても「部分」がどんなだか,どんなコードを実行してるか誰にも分かりません.

> 変数が範囲を超えているんだと思います。 

「思う」のではなく確認しなければ.


AS  2018-08-27 09:43:19  No: 49424

Mr.XRAYさん、原因は特定しました。

Delphiの関係者の方はここにはいないのですか??

ちょっと相談したいことができました。


AS  2018-08-27 09:54:33  No: 49425

igyさん
どんなプログラムか知られたくないのですが??

Delphiの関係者以外の方は、もうここに投稿はやめてください。

機会があれば、delphiの会社を訪問して、担当者と話をしたいと思います。


通りすがり  2018-08-27 09:56:49  No: 49426

日本法人のインフォメーションサービスセンターへどうぞ。
https://www.embarcadero.com/jp/company/contact-us-japan

(多分ここは中の人は見ていないので)


AS  2018-08-27 10:19:41  No: 49427

通りすがりさん、ありがとうございます。

皆さんも、いろいろ指導していただき、ありがとうございました。
解決済みを押してからの皆さんの投稿がなければ、
真の解決には至りませんでした。


igy  2018-08-27 19:44:25  No: 49428

> Delphiの関係者以外の方は、もうここに投稿はやめてください。 

AS さんから、投稿を禁じられているにもかかわらす、書き込むことをお許しください。

以下の部分、どうしても書きたかったもので・・・

> Mr.XRAYさん、原因は特定しました。 

> 解決済みを押してからの皆さんの投稿がなければ、 
> 真の解決には至りませんでした。 

原因が特定できて、真の解決に至ったのあれば、
何が原因だったのか、ここに書かれては、いかがですか?

> Delphiの関係者の方はここにはいないのですか?? 
> ちょっと相談したいことができました。 

> 機会があれば、delphiの会社を訪問して、担当者と話をしたいと思います。 

(差し障りない範囲で)この相談内容も、少しここに書いてみてはいかがでしょうか?
ここ見ている人が、相談に乗ってくれるかもしれませんよ。


Mr.XRAY  2018-08-27 19:52:06  No: 49429

> Delphiの関係者の方はここにはいないのですか??
> Delphiの関係者以外の方は、もうここに投稿はやめてください。

ということですが,
「ここ」はエンバカデロの公式のコミュニティの場ではありません.
エンバカデロの公式のコミュニティの場は以下です.日本語専用の場はありません.
このコミュニティの場でも,レスしている方の多くはエンバカデロの方ではありません.

https://community.embarcadero.com/2018-01-30-20-28-13/recent 

この Q and A も Delphi ML も個人の善意で運営され,成り立っています.
そのことを認識しておく必要があると思います.
もし,AS さんがエンバカデロ関係者以外からのレスが欲しくないというのであれば,
この掲示板で質問することを避けるしかありません.

エンバカデロ関係者以外はレスするなということは,レスする方がいなくなるということです.

[ 参考 ]
コミュニティの場は give & take ( ギブ・アンド・テイク )
http://mrxray.on.coocan.jp/Delphi/Others/013.htm#04

> Delphiの関係者以外の方は、もうここに投稿はやめてください。

ということですが,あえて投稿させて頂きました.


take  2018-08-27 20:16:08  No: 49430

多分もう本人から返信は無いと思いますが
原因は変数領域とかじゃないでしょ?

最初の方に、エラーが出るタイミングは?
と聞かれているのに何も答えてませんね。

エラーが発生した時でも良いのでデバッグを続ければ
どのイベント処理内で発生したかはわかるし
あとはそこからステップ実行すれば
問題がある行のところで同じエラーが出るでしょ

他の原因としてはASさんが、他の人のアドバイスにまったく耳を貸さず
勝手な思い込みで物事を進めていることでは無いでしょうか?


AS  2018-08-29 17:44:36  No: 49431

igyさん
私のプログラムミスでした。

takeさん
最初は、問題なく作動しているプログラムなので、プログラムミスは
ありえないと思っていたからですよ。

Mr.XRAYさん
もう、個人の力でどうこうできるレベルではないという意味なんですが??
最初は、UNIT3を追加したら何故エラーが出るのかという質問でしたが、
今は、なぜUNIT3を追加しないとエラーが出なかったのかになっています。

もう、本当にここでの投稿はやめましょう。
いつか会社に行って、相談しますから。


igy  2018-08-30 02:09:46  No: 49432

> igyさん 
> 私のプログラムミスでした。 

私が知りたいのは、実際に問題だったコードと、どのように修正して解決したか、です。


igy  2018-08-30 05:58:09  No: 49433

なお、
> 実際に問題だったコードと、どのように修正して解決したか、です。 
の例としては、

SetLengthで不可解なエラー
https://www.petitmonte.com/bbs/answers?question_id=8857

で、当初の見込みと違う箇所が問題だった場合でも、質問した人がきちんと、
問題だった箇所を説明しています。(2018/07/22(日) 17:31:00 投稿分)


AS  2018-08-30 16:54:12  No: 49434

igyさん

repeat
  dec(E)
  H[E]='';
unitl E<=-1;

0にするか、untilの前に置くべきですよね??

このミスは実がまだ修正していません。
いつか会社に行ったときにすぐに問題を起こせるようにするためです。
UNIT3のSTRA:integer;にして使用していますが、
全然エラーが起きないんですよね??
また、私の意図した作業はしているので、まったく問題はないんです。

このプログラムは8か月くらい使用しているのですが、
全然エラーは出ていないんですよ。
これが、私がUNIT1を調べなかった理由です。

では、では。


AS  2018-08-30 17:16:06  No: 49435

igyさん

上のは例ですので、本物とは別ですので。
dec(E)
の位置の問題だったということを言いたいだけですから。

紹介されたを見てみました。
ありがとうございました。


tor  2018-08-30 18:02:32  No: 49436

要するに H[-1] という範囲外の領域にアクセスしていたということでしょう?
メモリ上でその場所にたまたま何が置かれていたかによって
目に見える形でエラーになるか、目に見えぬままメモリが壊された状態で動き続けるかの違いだけです。

誰でも初心者の時に一度はやらかすミスですね。
このようなミスをした時に「一見関係ない変数を追加したり削除したり、順番や型を変えたりすることで
エラーが出たり出なくなったりする」現象が起きることはよく知られているし、
自身でそういう体験をした人も多くいるはずです。
だからこそ、回答者の方々もさんざんその可能性を指摘したし、
「範囲外チェックを有効にする」という確認方法も示されていましたよね。

仮のコードでもいいので、ASさんが早いうちにそのコードを提示していたなら
50以上もやりとりを重ねることなく瞬時に解決していたでしょうに、残念です。


take  2018-08-30 18:03:20  No: 49437

たった4行のサンプルプログラムにイライラしてしまうのですが・・・
とりあえずあるはずの1行を追加して

E := Length(H) + 1;
repeat 
  dec(E) 
  H[E]=''; 
unitl E<=-1; 

そして
1.エラーが起きないと思っていたが起きた。
2.変数HはString ではなく ShortStringで定義すべきだった
3.dec(E);の位置が悪いのが原因なのでそれで直ると思っている。

これに返答しようとすると
「見かけ上直るが行儀が悪く、今後の機能追加でバグが出る可能性がある」
という感じでしょうか?

問題の箇所を指摘しても聞く耳持たないだろうし、自身で考えた方が良いと思いますので、ここまでにしておきます。


igy  2018-08-30 19:48:43  No: 49438

ASさん、

> このミスは実がまだ修正していません。 
> いつか会社に行ったときにすぐに問題を起こせるようにするためです。 

とのことですが、もう会社に行く手間が省けましたね。

torさんが書かれた

> 要するに H[-1] という範囲外の領域にアクセスしていたということでしょう? 
> メモリ上でその場所にたまたま何が置かれていたかによって 
> 目に見える形でエラーになるか、目に見えぬままメモリが壊された状態で動き続けるかの違いだけです。 

で、納得できたでしょう?


AS  2018-08-31 16:41:34  No: 49439

皆さん、ありがとうございます。

納得はまだという感じですが、
確かにそういうことがあるのかもと思います。


AAA  2018-08-31 20:26:19  No: 49440

ポインタ系のバグは
バグを発生させる個所と実際にバグが発生する場所が異なる事があるからね

今回は
>「モジュール'AAA.exe'のアドレス0040B713deアドレスFFFFFFFFBに対する 
>読み取り土地違反が起きました。」 
で異常終了したけど

異常終了しないで
実行結果のみ予定外になるとかもあるからね


igy  2018-09-01 00:08:55  No: 49441

> 異常終了しないで 
> 実行結果のみ予定外になるとかもあるからね 

これ、経験ありますね。
配列に値を書き込むとき、添字が-1になってしまっていたことがあり、
別の集計用の配列の値が書き換えられてました。
(実際、ユーザーから指摘されるまで、気づきませんでした・・)

なので、

> このミスは実がまだ修正していません。 

> 全然エラーが起きないんですよね?? 
> また、私の意図した作業はしているので、まったく問題はないんです。 

まったく問題ないって思っていても、修正は、しておいたほうがよいとは、思います。


AS  2018-09-01 04:44:19  No: 49442

AAAさん、igyさん、ありがとうございます。

stringをintegerに変えるだけでエラーが起こるというのは、
確かにありうると思うんですが、
実際の自分のプログラムが8か月もエラーなしに存命できたことが
不思議でたまりません。この間に変数もいろいろ追加しています。

そして、実際に自分でエラーが起きない配列のプログラムできるのかと
思いました。

  for I := 1 to 1000 do H[i]:=STRA;

  for I := 0 to 1000 do EDit1.Text:=H[i];

どうしたら、このプログラムをエラーなしにできるでしょうか??


igy  2018-09-01 04:53:02  No: 49443

>  for I := 1 to 1000 do H[i]:=STRA; 
>
>  for I := 0 to 1000 do EDit1.Text:=H[i]; 
>
>どうしたら、このプログラムをエラーなしにできるでしょうか?? 

Hの宣言はどのようになってますか?
そして、最初のfor文は1から開始しているのに、次のfor文は0から開始しているのは、なぜですか?
あと、使用しているDelphiのバージョンとエディション は何ですか?


igy  2018-09-01 05:04:10  No: 49444

>どうしたら、このプログラムをエラーなしにできるでしょうか?? 

あと、エラーがでるのであれば、そのエラーの情報も、挙げたほうがよいかと思います。


igy  2018-09-01 09:54:36  No: 49445

それと、tor さんが、

> 要するに H[-1] という範囲外の領域にアクセスしていたということでしょう? 
> メモリ上でその場所にたまたま何が置かれていたかによって 
> 目に見える形でエラーになるか、目に見えぬままメモリが壊された状態で動き続けるかの違いだけです。 

と書いたとおりで、

> stringをintegerに変えるだけでエラーが起こるというのは、 
> 確かにありうると思うんですが、 
> 実際の自分のプログラムが8か月もエラーなしに存命できたことが 
> 不思議でたまりません。この間に変数もいろいろ追加しています。 

これ、考える意味あります?

AS さんのプログラムミスが原因なので、それを修正すれば、済む話では?


AS  2018-09-01 11:34:14  No: 49446

igyさん、ありがとうございます。

次のようなプログラムを組んでみました。
エラーは起きません。逆にどうしたらエラーが起こせるか疑問ですが??
H[10,-1]と書くと、エラー表示が出てコンパイルできないのに、
H[10,k]と書くとコンパイルできるのはちょっと感動しました。

igyさんは、最後まで付き合ってもらって、ありがとうございます。
これで、最後にします。
そして、プログラムも修正します。
-1を0に。

igyさんは、私みたいな素人にも優しいので好感が。
これからもよろしくお願いします。

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;
  H:array[0..100,1..10]of string;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  I,J,k:integer;
begin
  k:=-1;
  for I := 0 to 10 do for j:=1 to 10 do  H[i,j]:=IntTOStr(i)+'..'+intTostR(J);
  Edit1.Text:='10..-1';  Edit2.Text:=H[10,k];
end;


AS  2018-09-01 12:19:58  No: 49447

igyさん

一応、確かめてみないと、納得できないでしょう??

昔のbasicでは、K=-1でH[10,k]とすると実行時にエラーが出たと思います。
Delphiではチェックしていないということが確認できましたので、
それも収穫と思います。

本当に、ここはこれで最後にします。


通りすがり  2018-09-01 19:12:43  No: 49448

> プロジェクトオプションのDelphiコンパイラのコンパイルにある実行時エラーのオーバーフローチェックと 
> 範囲チェックにチェックオンして実行するとエラーで例外がでませんか? 

オプション変更後は一旦プロジェクトのクリーンアップをしてから再コンパイルしてください。


AS  2018-09-02 07:24:44  No: 49449

通りすがりさん、ありがとうございます。

言われた通りのチェック入れてコンパイルしましたが、
完璧にコンパイルされました。
上で表示したプログラムも、ここで質問しているプログラムも
エラー表示は出ませんでした。

しかし、これからは、ここにチェック入れてコンパイルしてみようと思います。

素人の私には知らないことが多いと思いました。


AS  2018-09-02 07:32:54  No: 49450

通りすがりさん、すみません。

コンパイルではなく、実行だったんですね。
ちゃんとエラー表示出ました。

ちょっと、難しいことを飛ばしてしまっていて、失礼しました。

ついでに、クリーンアップというのも分かりません。

ありがとうございました。


AS  2018-09-13 14:54:08  No: 49451

通りすがりさん

クリーンアップも分かったような気がします。
自作のプログラム全部見直しましたが、すべてにエラーがありました。

サイズも少し大きくなり、スピードもちょっと遅くなりますね。
4分かかっていた計算が4分30秒になりました。

けど、気になるようなものではないので、
チェックをつけた状態で、今後使用していきます。

ありがとうございました。


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








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