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}
var
STR:integer;
とすると,変数 STR には Integer 型の値しか代入できません.
var
STR:string;
とすると,変数 STR には string 型の値しか代入できません.
そういうこではないのですか ?
# 優れたプログラマは真似る
# 偉大なプログラマは盗む
判断するのに必要な情報がほとんどないので、断定できませんが、
> UNIT3の中の変数宣言の中の文字変数が原因でした。
実際は、これが原因では、ないかもしれませんね。
> パスワードを確認するプログラムUnit3を組み込んだら、
と書かれているのに、
> TForm3 = class(TForm)
> private
> { Private 宣言 }
> public
> { Public 宣言 }
> end;
それらしきものが一切ないのも謎ですし・・
変数 STR はグローバル変数になっていますから,それも要チェックですね.
( 別のユニット等でも同じ STR の定義があるとか)
> 判断するのに必要な情報がほとんどないので、
フォームの生成方法が自動生成なのか、コード上で生成しているのか、
もし自動生成の場合、UNIT1とUNIT3では、生成の順番がどのようになっているのか、
エラーが出るタイミングは、いつ出るのか、
UNIT3は、UNIT1のどのイベント(FormCreateとか?)で、表示しているのか・・あたりも気になりますね。
Mr-XRAYさん、igyさん、ありがとうございます。
単純にstring変数を宣言するだけでもエラーが出るんです
と言いたいために、簡単なunit3を記載しました。
実際には、ここで質問した後、無理やり解決しました。
UNIT3で宣言しているstring型変数1個を消してUNIT1で宣言している変数を使用すること、
UNIT3のstring型1個、integer型1個をProcedure内で宣言すること、
これで正常に動くようになりましたが、確認するために、
エラーが起きるようにもとに戻し、さらにエラーが起きないようにしたら、
まだエラーが出ました。
最後にUNIT1で使っている、VBで作成した英語と日本を話すプログラムを
使うProcedure2個を使用しないようにしたら、正常に動くように
なりました。
なんか、変数領域の限界まで使っているのではと思うんですが、
そんなことはありませんか??
ただし、UNIT3をメインプログラムにしてパスワードを確認してから、
UNIT1を呼び出すプログラムは正常に作動しています。
igyさん
>フォームの生成方法が自動生成なのか、コード上で生成しているのか、
意味がちょっと分かりません。
>もし自動生成の場合、UNIT1とUNIT3では、生成の順番がどのようになっているのか、
UNIT1からUNIT3を呼び出しています。
>エラーが出るタイミングは、いつ出るのか、
> UNIT3は、UNIT1のどのイベント(FormCreateとか?)で、表示しているのか・・あたりも気になりますね。
UNIT1のFormCreateで使っていますが、FormActivateで呼び出してもエラーが
出ることは変わりませんでした。
Mr-XRAYさん
>変数 STR はグローバル変数になっていますから,それも要チェックですね.
>( 別のユニット等でも同じ STR の定義があるとか)
もちろん、確認済です。
以前の質問で、XRAYさんの指摘されたことをメモしておきますと言ってましたが、
代わりに使ったプログラムで別のwin10のパソコンで文字化けが起こり、
正式採用に復帰したことを、感謝の気持ちを添えて、ご報告させていただきます。
ありがとうございました。
>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 内で定義した変数名が優先して使用されます.
implementation
STR:integer; //;string;
↓
implementation
var
STR:integer; //;string;
ちなみに str というのは同名の関数があります.
可能であれば変数名に使わない方が無難かも知れません
( Delphi は,変数名や関数名の大文字と小文字を区別しません)
http://docwiki.embarcadero.com/Libraries/Tokyo/ja/System.Str
Mr-XRAYさん、ありがとうございます。
implementation の下で宣言した変数がUNIT内だけのグローバル変数ということは、
初めて知りました。
usesの下で宣言しないといけないようですね。
ただ、やはり、Integerならエラーは出ませんが、Stringならエラーが出ます。
implementation
uses UNIT1,UNIT2;
var ASTR:integer; //;string;
integerとStringの違いは宣言した時に確保されるバイト数だと思うので、
どうしても、変数領域の範囲を超えてるのではと思うんですが??
そういうことはありませんか??
このパスワード確認ようのUNIT3は単独で使用できるようにしようと思っていますので、
UNIT1で宣言された変数を使くことは避けたいと思っています。
UNIT3で使っている文字変数の宣言を、stringではなくshortstringに変えたら、
問題はおこらなくなりました。
原因は、変数領域?のほとんどすべてを使っているからだと思うことにします。
ありがとうございました。
ShortStringはやめて…
というかこれで解決したと思うのは、本当にあり得ないので。
例外が発生してデバッガに制御が移ったときに、どのような処理で止まりますか?
それはUnit1、Unit2、Unit3のどのユニットですか?例外が発生して表示される行の直前の
処理が大体原因なのですが、そのあたりにブレークポイントをかけて、1行ずつ実行して
みたら何かわかりませんか?
あと、
> なんか、変数領域の限界まで使っているのではと思うんですが、
> そんなことはありませんか??
> 原因は、変数領域?のほとんどすべてを使っているからだと思うことにします。
絶対に違います。何か思い込みが激しいようですが、原因はあなたのコードにあります。
おそらく原因はグローバル変数領域のバッファオーバフローです。何らかの原因で
Form3(これはポインタ型)の次に配置されている変数に別の内容を上書きしてしまっています。
確かに以前から思い込みが非常に激しいようですね (笑).
他のユニットで使いたい変数は,一般的には public 部で定義します.
public 部で定義すると,定義したユニット名やフォーム名を付けて,
Form3.STR 等のようにしないと他のユニットからは使用できませんから,
トラブル発生の防止になります.
以下のような場所で定義するのは特別な場合です.
例えばフックのコールバック関数内で取得した値を処理する場合等です.
var
Form3: TForm3;
STR:integer; //;string;
[ 参考 ]
http://mrxray.on.coocan.jp/Delphi/plSamples/122_PluralForms.htm#list13
通りすがりさん、ありがとうございます。
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でこういうことは初めてです。
> 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です。
実行ファイルのサイズはプログラムに含まれるコードとデータ、それにデバッグ情報の合計で決まりますが、
ボタンなどのコントロールはいくつあってもコードは基本的に同じ量です。つまりプログラムの実行ファイルの
サイズはほぼあなたの書いたコードの量+プロジェクトオプションで指定したデバッグ情報の設定で決まります。
ちなみに実行時にメモリ上に取られるサイズはまた別の話です。
あー、なんか中途半端な書き込みになってしまいました。
> じゃなくてオーバランでこれらの領域を踏み潰している(↑のように)ということです。String型は
>裏でいろんな仕組みが働く型なので、その仕組みが異常を
検知してエラーになっている(Integerはそのような仕組みがなく、ShortStringはまた違う仕組み)と
いうことです。
連投になりますが、
> そして確かにエラーを起こす部分以外では正常に作動します。
そうではなくて、
> 例外が発生してデバッガに制御が移ったときに、どのような処理で止まりますか?
> それはUnit1、Unit2、Unit3のどのユニットですか?例外が発生して表示される行の直前の
> 処理が大体原因なのですが、そのあたりにブレークポイントをかけて、1行ずつ実行して
> みたら何かわかりませんか?
は答えてもらえませんか?
>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 は使用していない適当な名前
今回のこの現象はハッキリさせた方がいいと思いますよ.
この掲示板は多くの方が観ています.誤解を招く恐れがあります.
今回のこの現象は,通常では考えられない現象です.
var
Form3: TForm3;
STR:integer; //;string;
AS さんはこの部分以外に STR と言う変数には一切触れていません.
と言うことは,他で STR という変数を使っていないと解釈すると,
> STRをstringにしたらエラーが出て、integerにしたらエラーは出ません。
と言うエラーが発生するハズがありません.
とすると,それは Delphi のバグということになってしまいます.
AS さんはそう言いたげな雰囲気のようです.
私が使っている Delphi では発生しませんが.
AAAさん、一番最初に示しているSTRはUNIT,UNIT2,UNIT3どこでも使用していません。
よって、コンパイルはできるんです。
STRをstringにすると、UNIT1でエラーが出るんです。
通りすがりさん
いろいろ書いてもらって、ありがとうございます。
4バイトというのは、場所だけ指定するんでしょうね??
場所を特定するという作業は、プログラムを変更していますので、
元に戻してまでは、できません。また、integerにしたらエラーは出ないし、
UNIT3を入れるまでは、エラーは起こっていなかったので、プログラムミスは
ないと思っています。
変数領域が大きすぎたのが原因だと思います。
サイズの話ですが、電卓のプログラムなんてものすごく単純ですよね?
それが何で60UNITの膨大な、自分でもよくわからなくなるようなプログラムの
サイズのほうが少ないのか、お聞きしたいのですが??
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を使ったプログラムのサイズより
大きくなるのか、教えてもらえませんか??
> 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.
> 実際、配列変数の量を1/4にしましたが、エラーは出なくなりましたよ。
最初の質問では、配列変数に関しては、一切触れられていないみたいですが、
その配列変数を含む、エラーを再現できるコードをここに挙げてみるのは、いかがですか?
(他の人が検証できるように、新規プロジェクトから作成して、エラーが出るコードを)
自分の空想に浸るのは公開の場ではやめましょう。
> STRをstringにすると、UNIT1でエラーが出るんです。
> > 例外が発生してデバッガに制御が移ったときに、どのような処理で止まりますか?
> > それはUnit1、Unit2、Unit3のどのユニットですか?例外が発生して表示される行の直前の
> > 処理が大体原因なのですが、そのあたりにブレークポイントをかけて、1行ずつ実行して
> > みたら何かわかりませんか?
>
> は答えてもらえませんか?
> プロジェクトオプションのDelphiコンパイラのコンパイルにある実行時エラーのオーバーフローチェックと
> 範囲チェックにチェックオンして実行するとエラーで例外がでませんか?
プログラムサイズの話はいい質問だとは思いますが、とっちらかってしまうので別に質問されたら
いかがですか?ファイルサイズの話、実行時にメモリにメモリサイズの話、いろいろありますので。
あとエラーが発生したときは、それがコンパイル時なのか実行時なのかをはっきり書いてください。
またそのときのエラーメッセージはコピペで1文字の間違いもなく提示してください。
コンパイル時ならIDEに表示されているエラーメッセージを選択して右クリック→コピーで、
実行時ならエラーダイアログでCtrl+Cでクリップボードにコピーできます。
どっかでメモリ確保し忘れて(もしくは足りない)
そのメモリにアクセスしにいって
そのアドレスが変数で確保してるメモリとかぶってる
かな?
>どっかでメモリ確保し忘れて(もしくは足りない)
(以下,略)
配列という新たな登場がありましたからね.
そもそも
『モジュール Project1.exe のアドレス〇〇でアドレス〇〇に 対する読み込み (書き込み) 違反がおきました。』
というエラーはメモリのアクセス違反のエラーですからね.
(1) 解放済みのメモリにアクセスしようとした
(2) 確保していないメモリにアクセスしようとした
(3) 作成されていないオブジェクトに何かしようとした
(4) 解放済みのオブジェクトに何かしようとした
(5) 生成していなフォームの何かにアクセスした
等々ですよね.
配列のサイズを 1/4 にしたら例外 (?) が発生しなくなったと書いていますが,
配列のサイズの問題だとすると String 型の定義で例外が発生して,
Integer 型と ShortString 型だと例外が発生しない説明が付きません.
String 型よりも ShortString 型の方が定義した初期段階ではメモリを使いますから.
# 配列のサイズが原因だと別の例外かエラーなるのでは...
String型はmanagedなので、その変数領域(文字列保持領域ではなく)を踏み潰すとPODな型と違って
メモリマネージャかRTLがエラります。
(ShortStringはarray [0..255] of AnsiCharですからmanagedではない)
>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 に対する読み取り違反がおきました。.
あてずっぽうではあるのですが、Unit2のinterface部のForm2: TForm2;の次に何らかの配列変数があって、
この配列への書き込みでオーバランしてForm3や次のStrを踏み抜いているんじゃないかと想像してます。
え、減らしたらエラーが出ない?もっと後ろを踏み抜いたけど顕在化してないだけじゃないですか?
>この配列への書き込みでオーバランして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;
>プロジェクトを [ビルド] (再構築) すると,
プロジェクトを [ビルド] (再構築) してから実行すると,ですね.
動作確認は Windows 7 U64(SP1) + Delphi XE5(UP2) Pro VCL-32 です.
> この配列への書き込みでオーバランしてForm3や次のStrを踏み抜いているんじゃないかと想像してます。
これで Integer, ShortString 型だと例外が発生しないのが理解できますね.
Integer 型も ShortString 型も変数を定義した段階で領域が確保されますから.
Delphiの限界を試すプログラムを作って、自分の配列より大きくしても、
エラーは出ませんでした。で、もう一度、エラーの出るプログラムを再現してみました。
最初に示したUNIT3を使って、確認しました。
コンパイルは正常にすべてできます。エラーはすべて同じ場所で起こります。
4個の選択肢表示する部分で起こります。変数が範囲を超えているんだと思います。
(1)UNIT1の配列変数を減らしてもエラーは消えません。
(2)STRA:string;をpriveteで宣言するとエラーは消えます。
(3)implementationの下においてもエラーは消えません。
(4)STR:integer;にするとエラーは消えます。
変数の個数を減らしたら直ったというのその時だけだったようです。
いろいろほかの部分も変更したので、現在は問題ありません。
UNIT2のことでは、ボタンが9個ラベルが9個あるだけですから、問題ではありません。
UNIT1,UNIT2だけでコンパイルすると、何も問題はないので、UNIT1やUNIT2について
考えても無駄だと思っていますが、また今後万一何か異常が出たら考えてみたいと思います。
1個のボタンだけのFormをコンパイルすると、10531KBの大きさがありました。
まあ、こういうことなんだと思っておくことにしました。
大きさに関する質問は取り消します。
> STRをstringにすると、UNIT1でエラーが出るんです。
> 例外が発生してデバッガに制御が移ったときに、どのような処理で止まりますか?
> それはUnit1、Unit2、Unit3のどのユニットですか?例外が発生して表示される行の直前の
> 処理が大体原因なのですが、そのあたりにブレークポイントをかけて、1行ずつ実行して
> みたら何かわかりませんか?
> プロジェクトオプションのDelphiコンパイラのコンパイルにある実行時エラーのオーバーフローチェックと
> 範囲チェックにチェックオンして実行するとエラーで例外がでませんか?
> あとエラーが発生したときは、それがコンパイル時なのか実行時なのかをはっきり書いてください。
> またそのときのエラーメッセージはコピペで1文字の間違いもなく提示してください。
> コンパイル時ならIDEに表示されているエラーメッセージを選択して右クリック→コピーで、
> 実行時ならエラーダイアログでCtrl+Cでクリップボードにコピーできます。
> で、もう一度、エラーの出るプログラムを再現してみました。
>
> 最初に示したUNIT3を使って、確認しました。
> コンパイルは正常にすべてできます。エラーはすべて同じ場所で起こります。
> 4個の選択肢表示する部分で起こります。変数が範囲を超えているんだと思います。
> (1)UNIT1の配列変数を減らしてもエラーは消えません。
> (2)STRA:string;をpriveteで宣言するとエラーは消えます。
> (3)implementationの下においてもエラーは消えません。
> (4)STR:integer;にするとエラーは消えます。
他の人が検証できるように、このソースコードを、ここに挙げてみるのは、いかがですか?
> 4個の選択肢表示する部分で起こります。
と書かれても「部分」がどんなだか,どんなコードを実行してるか誰にも分かりません.
> 変数が範囲を超えているんだと思います。
「思う」のではなく確認しなければ.
Mr.XRAYさん、原因は特定しました。
Delphiの関係者の方はここにはいないのですか??
ちょっと相談したいことができました。
igyさん
どんなプログラムか知られたくないのですが??
Delphiの関係者以外の方は、もうここに投稿はやめてください。
機会があれば、delphiの会社を訪問して、担当者と話をしたいと思います。
日本法人のインフォメーションサービスセンターへどうぞ。
https://www.embarcadero.com/jp/company/contact-us-japan
(多分ここは中の人は見ていないので)
通りすがりさん、ありがとうございます。
皆さんも、いろいろ指導していただき、ありがとうございました。
解決済みを押してからの皆さんの投稿がなければ、
真の解決には至りませんでした。
> Delphiの関係者以外の方は、もうここに投稿はやめてください。
AS さんから、投稿を禁じられているにもかかわらす、書き込むことをお許しください。
以下の部分、どうしても書きたかったもので・・・
> Mr.XRAYさん、原因は特定しました。
> 解決済みを押してからの皆さんの投稿がなければ、
> 真の解決には至りませんでした。
原因が特定できて、真の解決に至ったのあれば、
何が原因だったのか、ここに書かれては、いかがですか?
> Delphiの関係者の方はここにはいないのですか??
> ちょっと相談したいことができました。
> 機会があれば、delphiの会社を訪問して、担当者と話をしたいと思います。
(差し障りない範囲で)この相談内容も、少しここに書いてみてはいかがでしょうか?
ここ見ている人が、相談に乗ってくれるかもしれませんよ。
> 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の関係者以外の方は、もうここに投稿はやめてください。
ということですが,あえて投稿させて頂きました.
多分もう本人から返信は無いと思いますが
原因は変数領域とかじゃないでしょ?
最初の方に、エラーが出るタイミングは?
と聞かれているのに何も答えてませんね。
エラーが発生した時でも良いのでデバッグを続ければ
どのイベント処理内で発生したかはわかるし
あとはそこからステップ実行すれば
問題がある行のところで同じエラーが出るでしょ
他の原因としてはASさんが、他の人のアドバイスにまったく耳を貸さず
勝手な思い込みで物事を進めていることでは無いでしょうか?
igyさん
私のプログラムミスでした。
takeさん
最初は、問題なく作動しているプログラムなので、プログラムミスは
ありえないと思っていたからですよ。
Mr.XRAYさん
もう、個人の力でどうこうできるレベルではないという意味なんですが??
最初は、UNIT3を追加したら何故エラーが出るのかという質問でしたが、
今は、なぜUNIT3を追加しないとエラーが出なかったのかになっています。
もう、本当にここでの投稿はやめましょう。
いつか会社に行って、相談しますから。
> igyさん
> 私のプログラムミスでした。
私が知りたいのは、実際に問題だったコードと、どのように修正して解決したか、です。
なお、
> 実際に問題だったコードと、どのように修正して解決したか、です。
の例としては、
SetLengthで不可解なエラー
https://www.petitmonte.com/bbs/answers?question_id=8857
で、当初の見込みと違う箇所が問題だった場合でも、質問した人がきちんと、
問題だった箇所を説明しています。(2018/07/22(日) 17:31:00 投稿分)
igyさん
repeat
dec(E)
H[E]='';
unitl E<=-1;
0にするか、untilの前に置くべきですよね??
このミスは実がまだ修正していません。
いつか会社に行ったときにすぐに問題を起こせるようにするためです。
UNIT3のSTRA:integer;にして使用していますが、
全然エラーが起きないんですよね??
また、私の意図した作業はしているので、まったく問題はないんです。
このプログラムは8か月くらい使用しているのですが、
全然エラーは出ていないんですよ。
これが、私がUNIT1を調べなかった理由です。
では、では。
igyさん
上のは例ですので、本物とは別ですので。
dec(E)
の位置の問題だったということを言いたいだけですから。
紹介されたを見てみました。
ありがとうございました。
要するに H[-1] という範囲外の領域にアクセスしていたということでしょう?
メモリ上でその場所にたまたま何が置かれていたかによって
目に見える形でエラーになるか、目に見えぬままメモリが壊された状態で動き続けるかの違いだけです。
誰でも初心者の時に一度はやらかすミスですね。
このようなミスをした時に「一見関係ない変数を追加したり削除したり、順番や型を変えたりすることで
エラーが出たり出なくなったりする」現象が起きることはよく知られているし、
自身でそういう体験をした人も多くいるはずです。
だからこそ、回答者の方々もさんざんその可能性を指摘したし、
「範囲外チェックを有効にする」という確認方法も示されていましたよね。
仮のコードでもいいので、ASさんが早いうちにそのコードを提示していたなら
50以上もやりとりを重ねることなく瞬時に解決していたでしょうに、残念です。
たった4行のサンプルプログラムにイライラしてしまうのですが・・・
とりあえずあるはずの1行を追加して
E := Length(H) + 1;
repeat
dec(E)
H[E]='';
unitl E<=-1;
そして
1.エラーが起きないと思っていたが起きた。
2.変数HはString ではなく ShortStringで定義すべきだった
3.dec(E);の位置が悪いのが原因なのでそれで直ると思っている。
これに返答しようとすると
「見かけ上直るが行儀が悪く、今後の機能追加でバグが出る可能性がある」
という感じでしょうか?
問題の箇所を指摘しても聞く耳持たないだろうし、自身で考えた方が良いと思いますので、ここまでにしておきます。
ASさん、
> このミスは実がまだ修正していません。
> いつか会社に行ったときにすぐに問題を起こせるようにするためです。
とのことですが、もう会社に行く手間が省けましたね。
torさんが書かれた
> 要するに H[-1] という範囲外の領域にアクセスしていたということでしょう?
> メモリ上でその場所にたまたま何が置かれていたかによって
> 目に見える形でエラーになるか、目に見えぬままメモリが壊された状態で動き続けるかの違いだけです。
で、納得できたでしょう?
皆さん、ありがとうございます。
納得はまだという感じですが、
確かにそういうことがあるのかもと思います。
ポインタ系のバグは
バグを発生させる個所と実際にバグが発生する場所が異なる事があるからね
今回は
>「モジュール'AAA.exe'のアドレス0040B713deアドレスFFFFFFFFBに対する
>読み取り土地違反が起きました。」
で異常終了したけど
異常終了しないで
実行結果のみ予定外になるとかもあるからね
> 異常終了しないで
> 実行結果のみ予定外になるとかもあるからね
これ、経験ありますね。
配列に値を書き込むとき、添字が-1になってしまっていたことがあり、
別の集計用の配列の値が書き換えられてました。
(実際、ユーザーから指摘されるまで、気づきませんでした・・)
なので、
> このミスは実がまだ修正していません。
>
> 全然エラーが起きないんですよね??
> また、私の意図した作業はしているので、まったく問題はないんです。
まったく問題ないって思っていても、修正は、しておいたほうがよいとは、思います。
AAAさん、igyさん、ありがとうございます。
stringをintegerに変えるだけでエラーが起こるというのは、
確かにありうると思うんですが、
実際の自分のプログラムが8か月もエラーなしに存命できたことが
不思議でたまりません。この間に変数もいろいろ追加しています。
そして、実際に自分でエラーが起きない配列のプログラムできるのかと
思いました。
for I := 1 to 1000 do H[i]:=STRA;
for I := 0 to 1000 do EDit1.Text:=H[i];
どうしたら、このプログラムをエラーなしにできるでしょうか??
> 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のバージョンとエディション は何ですか?
>どうしたら、このプログラムをエラーなしにできるでしょうか??
あと、エラーがでるのであれば、そのエラーの情報も、挙げたほうがよいかと思います。
それと、tor さんが、
> 要するに H[-1] という範囲外の領域にアクセスしていたということでしょう?
> メモリ上でその場所にたまたま何が置かれていたかによって
> 目に見える形でエラーになるか、目に見えぬままメモリが壊された状態で動き続けるかの違いだけです。
と書いたとおりで、
> stringをintegerに変えるだけでエラーが起こるというのは、
> 確かにありうると思うんですが、
> 実際の自分のプログラムが8か月もエラーなしに存命できたことが
> 不思議でたまりません。この間に変数もいろいろ追加しています。
これ、考える意味あります?
AS さんのプログラムミスが原因なので、それを修正すれば、済む話では?
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;
igyさん
一応、確かめてみないと、納得できないでしょう??
昔のbasicでは、K=-1でH[10,k]とすると実行時にエラーが出たと思います。
Delphiではチェックしていないということが確認できましたので、
それも収穫と思います。
本当に、ここはこれで最後にします。
> プロジェクトオプションのDelphiコンパイラのコンパイルにある実行時エラーのオーバーフローチェックと
> 範囲チェックにチェックオンして実行するとエラーで例外がでませんか?
オプション変更後は一旦プロジェクトのクリーンアップをしてから再コンパイルしてください。
通りすがりさん、ありがとうございます。
言われた通りのチェック入れてコンパイルしましたが、
完璧にコンパイルされました。
上で表示したプログラムも、ここで質問しているプログラムも
エラー表示は出ませんでした。
しかし、これからは、ここにチェック入れてコンパイルしてみようと思います。
素人の私には知らないことが多いと思いました。
通りすがりさん、すみません。
コンパイルではなく、実行だったんですね。
ちゃんとエラー表示出ました。
ちょっと、難しいことを飛ばしてしまっていて、失礼しました。
ついでに、クリーンアップというのも分かりません。
ありがとうございました。
通りすがりさん
クリーンアップも分かったような気がします。
自作のプログラム全部見直しましたが、すべてにエラーがありました。
サイズも少し大きくなり、スピードもちょっと遅くなりますね。
4分かかっていた計算が4分30秒になりました。
けど、気になるようなものではないので、
チェックをつけた状態で、今後使用していきます。
ありがとうございました。