📄 wpw_wapi_res_95.html
字号:
<HTML>
<HR><A NAME=WINAPI_RES_EDITCONTROL>
Return to <a href="wpw_wapi_index.html#TOC">Table of Contents for this chapter</a><br>
<H4>Subject: Windows resource and Text EDIT control</H4><PRE>
Recently there was a discussion in comp.lang.pascal
regarding what appeared to be a limit on the
number of TEdit controls that could exist
within a Delphi application. The debate raged
as to whether it was a Delphi bug or
a Windows limitation. Accoringly I
would like to hear form those who know
what the real story is:
Briefly it was found that when a tabbed
notebook with approximately 150 TEdit
controls was made visible then the app
crashed with an EOutOfResources Exception.
This appeared to be a generic problem when
about 220 child windows were open on the
same app. However it appeared that there
were plenty of local and plenty of global
resoruces available both by the GetFreeSystemResources
functions and the ability to run other
Windows apps. Additionally there appeared to
be plenty of local system resources (stack,
local heap and static data) available.
What follows is the most recent posting
regarding this issue. IF youve got any comments
I'd be interested to hear them:
--------------------------------------------
Hi Brad,
Firstly let me say that
I spend most of my time in OSF/1 networking
so Im not a Windows guru rather more of a novice
so as I said this is a lot of conjecture.
In article <3rm92c$7ct@nntpd.lkg.dec.com> you wrote:
: After much discussion the problem has been found, many
: thanks go to Chuck Jazdzewski from Borland.
: A little explanation and then a solution. The following
: is somewhat conjecture.
: The real problem is the TEdit class which I presume
: (I dont have source code) is based on the native
: Windows Edit control. When each program starts
It is not based on it, it is a Window's Edit control.
The TEdit is ONLY an object "wrapper".
That could well be, as I dont have the source code for
the VCL library I cant confirm or deny this but I suspect
you are correct.
: in Windows the USER.EXE module assigns a "secret"
: 64k heap to store such things as windows handles,
This does not happen when each programs starts, but
when WINDOWS starts. 64k is ALL there is for ALL
windows.
As I said i dont know ebnough to argue on this point
However two things are against what you say:
1: Borland Delphi team who are, you must admit,
preety familiar with Windows internals say not
2: When the problem happens I can still run many
other large applications in Windows without exiting
the problem causing app. It is implicit that
the problem is local to the App and is absolutely
NOT a global problem with Windows as there are
plenty of global resources to load and run other
apps when the problem IS occurring (see below).
3: Both fixes presented solve the problem
: menu handles and other data. This is not the
: When components such as TEdit are contained on
: a "persistant" item such as a notebook these
: components do not go away while the parent form is
: still in existance.
I'll look at the source code and see what I can find.
If they do not go away, WinSight should see them as
child windows.
It does but I would appreciate any insight you can give
as I am reticent to invest any more time in the Delphi
port in case there are any more "gotchas" like this
one.
: Now TEdit has a default string length of 255 characters, the
: length is not a functionof the MaxSize property.
: Guess where the string is stored? Give up? well
: it is stored in the USER.EXE secret heap. 200
This heap is hardly a secret. The API function
GetFreeSystemResources will tell you what is available.
This function returns plenty of resources when the
problem happens. As I had the argument/discussion with Vince
this is not the Global Windows heap which most
people know about nor is it the local 64k heap
allocated to each program. From what I can glen
this is a third heap that acts like a cache that
Windows allocates to each prog that it has running
and is NOT documented!!
: or so TEdits and you have used up all your
: USER.EXE heap.
Absolutely false. The Edit control global allocates
memory for it's storage. Delphi may duplicate this
but it would come out of the data segment or the stack
depending on how it is allocated. The windows max length
is 64k (actually slightly less than) You can get 32k
without any work at all. I have a program running now
with 4 or 5 64k edit controls open and still have plenty
of system resources.
Ok I will believe you. I think this discussion has pointed
out some serious problem with Delphi and/or Windows. Whatever
the case it should be held in the public domain so
Ill will post this reply to the group for open discussion.
Like you I have other Windows apps which have 500+ child
windows with no problems, although they are not all Edit Controls.
: So the take home message is: TEdit is especially
: dangerous in this regard because of its large
: usage, use sparingly.
No it is not, see above. One thing that may be happening
is that Delphi is reserving extra bytes in the window class
which are stored in the user heap, but I find it hard to believe
that they are storing more than a few bytes this way. Any
more would be absolutely stupid.
No you may be incorrect, you have missed the previous discussion,
there is plenty of the following left over when the problem happens:
1: Local heap
2: local stack
3: data
4: global system resources
As to whether they are storing extra bytes in the class
I dont know, wouild have to have a look at the VCL source
when I can afford to buy it!!
: You analized it correctly. The TEdit is more than the 20 characters
: but VCL can't do much about it since it is the Windows edit control.
: We can't do much about how much it stores but you can change where it
: stores the data. Below is a new control TNLEdit (for non-local edit)
: that stores the data in global memory instead of "local" storage. If
: you replace all you edit controls with this control won't run into
: the problem. I create several thousand of these edit controls where
: I could only create 250 normal edit controls.
This is different. A normal edit control takes it's storage space
from the parent window's data space. (Not the "secret" heap). The
do you mean the applications local heap instead of the "parent windows
data space" ?
non-local edit control described below is merely an edit control
that stores it's data on the global heap. The limit of 250 probably
came from the 255 control limit of a dialog. (Or the parent ran out
of data space and could not create any more) To create a control like
this take a look at the DS_LOCALEDIT creation style and the
EM_SETHANDLE
and the EM_GETHANDLE messages (yes, it's API time)
You lost me back at the train station :-) But I do know that this NOT
a local heap or a global resource probelm for the reasons stated above:
1: there is no local heap/stack shortage
2: there is no global resource problem
when the probelm is actually happening i.e. with out
closing the bombing app. I can even start a second instance
of the app which will "crash" at the same point.
Having just looked at what they are doing below, I don't think that
they have done it quite right. You should pass the hiword of the
pointer returned by Globallock to LocalInit to create a data segment
for the edit control to use. They seem to have skipped that part.
All of this is in a file called GLBEDIT.EXE at ftp.microsoft.com//
softlib/mslfiles. I am somewhat familiar with it because this is
the only way that I have ever found to get an edit control to hold
more than 32k. But then I have gotten a quite a few wrong answers
from Borland Tech support.
Ok thanks for your insights Brad, however both the fixes work for
my purposes and definitely solve the problem.
Just out of interest my machine reports the following
resources when the problem occurrs while running
the app outside of Delphi:
free system resources: 50%
free gdi resources: 67%
free user resources: 50%
free local stack: 22k
free local heap: 11k
free global heap: 8M
largest global: 2M
As you can see there is no problem here
----------------------------------------
PS there were two fixes/workarounds for this problem:
1: Send a WM_CLOSE to each child Window as it becomes invisible
2: Rewrite the TEdit code to do a globalAlloc() for its text buffer
These are detailed in the series of articles in comp.lang.pascal
if interested. I think the real questions are:
1: Is there a third "secret" 64k heap used by Windows
2: Where is the text for a TEdit (or an Edit control) stored.
3: Is ti possible to get an OutOfResources exception when
the GetFreeResources returns lots of spare space ?
and if so how and why and which resource is in short supply ?
4: Is there a limit in how much of the 64k global pie an app can have ?
5: Does anyone know of any other instances where 220+ edit controls
use up too much of anything ?.
Thanks for your time,
Jon
--
----------------------------------------------------------------------
Name: Dr Jon Jenkins
Location: Digital Equipment Corp, NaC,
Burnett Place, Research Park,
Bond University, Gold Coast
QLD, AUSTRALIA 4229
Phone: 61-75-75-0151
Fax: 61-75-75-0100
Internet: jenkinsj@ozy.dec.com
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -