<br><br><div class="gmail_quote">On Wed, Mar 10, 2010 at 6:39 AM, Jon Hylands <span dir="ltr">&lt;<a href="mailto:jon@huv.com">jon@huv.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">On Fri, 19 Feb 2010 16:25:20 -0500, Jon Hylands &lt;<a href="mailto:jon@huv.com">jon@huv.com</a>&gt; wrote:<br>
<br>
&gt;I&#39;m getting a weird problem, and its been so many years since I saw<br>
&gt;this, I&#39;m at a loss as to what to do...<br>
&gt;<br>
&gt;On my robot Brainbot, I have a 2.83 GHz Core 2 Quad with 2 GB RAM and<br>
&gt;a 32 GB solid state HD. It is running Windows XP Pro.<br>
&gt;<br>
&gt;I&#39;m getting a Low Space Notifier whenever I try and copy text to the<br>
&gt;clipboard, or when I try and paste. I can do other development things,<br>
&gt;writing a saving code, and opening browsers and windows with no<br>
&gt;problems.<br>
&gt;<br>
&gt;Task Manager says Squeak is taking up 37,980 K, and the machine has<br>
&gt;1.2 GB of free physical memory.<br>
&gt;<br>
&gt;I&#39;m running the following VM:<br>
&gt;<br>
&gt;Squeak 3.10.6 (release) from Aug 30 2007<br>
&gt;<br>
&gt;And the following image:<br>
&gt;<br>
&gt;Squeak 3.10.2<br>
&gt;latest update: #7179<br>
<br>
</div>Okay, so this is still bothering me, and I dug a little deeper, and<br>
came across something that blew me away...<br>
<br>
<a href="http://www.huv.com/Clipboard-OutOfMemory.png" target="_blank">http://www.huv.com/Clipboard-OutOfMemory.png</a><br>
<br>
Basically, when I do &#39;copy&#39;, the primitive returns a ByteString that<br>
is 4 billion bytes long -- 2^32 - 1 to be exact. Clearly that is not<br>
really allocated, because even when I have this inspector open, Squeak<br>
is still only taking about 37 MB of memory.<br>
<br>
However, the method String &gt;&gt; #withSqueakLineEndings is trying to<br>
create a new string that is 4 billion bytes long, and that is where I<br>
run into the low space warning.<br>
<br>
Primitive 141 appears to be causing the issue.<br></blockquote><div><br></div><div>The primitive looks like this in my quite possibly obsolete VM sources:</div><div><br></div><div>primitiveClipboardText</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;When called with a single string argument, post the string to </div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>the clipboard. When called with zero arguments, return a </div><div><span class="Apple-tab-span" style="white-space:pre">        </span>string containing the current clipboard contents.&quot;</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>| s sz |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>argumentCount = 1</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [s := self stackTop.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>(self isBytes: s) ifFalse: [^ self primitiveFail].</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self successful</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [sz := self stSizeOf: s.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span>self clipboardWrite: sz From: s + BaseHeaderSize At: 0.</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>self pop: 1]]</div><div>
<span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [sz := self clipboardSize.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>(self sufficientSpaceToAllocate: sz) ifFalse:[^self primitiveFail].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>s := self instantiateClass: (self splObj: ClassString) indexableSize: sz.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self clipboardRead: sz Into: s + BaseHeaderSize At: 0.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>self pop: 1 thenPush: s]</div><div><br></div><div>I&#39;m willing to bet that clipboardSize is returning -1.</div><div><br></div><div>It probably needs to read something like</div>
<div><br></div><div>primitiveClipboardText</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;When called with a single string argument, post the string to </div><div><span class="Apple-tab-span" style="white-space:pre">        </span>the clipboard. When called with zero arguments, return a </div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>string containing the current clipboard contents.&quot;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| s sz |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>argumentCount = 1</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [s := self stackTop.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>(self isBytes: s) ifFalse: [^ self primitiveFail].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>self successful</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [sz := self stSizeOf: s.</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>self clipboardWrite: sz From: s + BaseHeaderSize At: 0.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span>self pop: 1]]</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [sz := self clipboardSize.</div><div>&gt;&gt;<span class="Apple-tab-span" style="white-space:pre">                        </span>(sz &gt;= 0 and: [self sufficientSpaceToAllocate: sz]) ifFalse:[^self primitiveFail].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>s := self instantiateClass: (self splObj: ClassString) indexableSize: sz.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self clipboardRead: sz Into: s + BaseHeaderSize At: 0.</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>self pop: 1 thenPush: s] </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
I&#39;m not much of a VM person, so hopefully someone who is can look at<br>
that primitive and figure out what case is causing it.<br>
<br>
One more thing to note - I&#39;m running Windows in a Remote Desktop, from<br>
a Linux machine. To clarify, my development machine is a desktop,<br>
running Ubuntu linux. The robot is a mini-itx running Windows XP Pro.<br>
I use remote desktop from linux to access the Windows GUI on the<br>
robot.<br></blockquote><div><br></div><div>The Windows VM&#39;s clipboardText function is a tad unsafe:</div><div><br></div><div>int clipboardSize(void) {</div><div>  HANDLE h;</div><div>  WCHAR *src;</div><div>  unsigned char *tmp;</div>
<div>  int i, count, bytesNeeded;</div><div><br></div><div>  /* Do we have text in the clipboard? */</div><div>  if(!IsClipboardFormatAvailable(CF_UNICODETEXT))</div><div>    return 0;</div><div><br></div><div>  if(!OpenClipboard(stWindow))</div>
<div>    return 0;</div><div><br></div><div>  /* Get it in unicode format. */</div><div>  h = GetClipboardData(CF_UNICODETEXT);</div><div>  src = GlobalLock(h);</div><div><br></div><div>  /* How many bytes do we need to store those unicode chars in UTF8 format? */</div>
<div>  bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, src, -1,</div><div>                    NULL, 0, NULL, NULL );</div><div>  tmp = malloc(bytesNeeded+1);</div><div><br></div><div>  /* Convert Unicode text to UTF8. */</div>
<div>  WideCharToMultiByte(CP_UTF8, 0, src, -1, tmp, bytesNeeded , NULL, NULL);</div><div><br></div><div>  /* Count CrLfs for which we remove the extra Lf */</div><div>  count = bytesNeeded; /* ex. terminating zero */</div>
<div>  for(i=0; i&lt;count; i++) {</div><div>    if((tmp[i] == 13) &amp;&amp; (tmp[i+1] == 10)) bytesNeeded--;</div><div>  }</div><div>  bytesNeeded--; /* discount terminating zero */</div><div>  free(tmp); /* no longer needed */</div>
<div><br></div><div>  GlobalUnlock(h);</div><div>  CloseClipboard();</div><div><br></div><div>  return bytesNeeded;</div><div>}</div><div><br></div><div>If bytesNeeded is zero then the function will return (int)-1. </div>
<div><br></div><div>From the MS manual page:</div><div><br></div><div><span class="Apple-style-span" style="font-family: &#39;Segoe UI&#39;, Verdana, Arial; font-size: 12px; "><h3 style="font-family: &#39;Segoe UI&#39;, Verdana, Arial; font-size: 1.1666em; color: rgb(63, 82, 156); font-weight: bold; ">
Return Value</h3><p>Returns the number of bytes written to the buffer pointed to by <em>lpMultiByteStr</em> if successful. If the function succeeds and <em>cbMultiByte</em> is 0, the return value is the required size, in bytes, for the buffer indicated by <em>lpMultiByteStr</em>.</p>
<p>The function returns 0 if it does not succeed. To get extended error information, the application can call <strong>GetLastError</strong>, which can return one of the following error codes:</p><ul><li>ERROR_INSUFFICIENT_BUFFER. A supplied buffer size was not large enough, or it was incorrectly set to NULL.</li>
<li>ERROR_INVALID_FLAGS. The values supplied for flags were not valid.</li><li>ERROR_INVALID_PARAMETER. Any of the parameter values was invalid.</li><li>ERROR_NO_UNICODE_TRANSLATION. Invalid Unicode was found in a string.</li>
</ul><div><br></div><div><span class="Apple-style-span" style="font-family: arial; font-size: small; "><div>So something like</div><div><br></div><div><span class="Apple-style-span" style="font-family: arial; "><div>  /* How many bytes do we need to store those unicode chars in UTF8 format? */</div>
<div>     bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, src, -1,</div><div>                    NULL, 0, NULL, NULL );</div><div>     if (bytesNeeded &lt;= 0)</div><div>          return 0;</div><div><br></div><div>would be wise.</div>
<div> </div></span></div></span></div></span></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
Later,<br>
<font color="#888888">Jon<br>
<br>
<br>
</font></blockquote></div><br>