On Fri, Jan 30, 2015 at 6:32 AM, Ben Coman <[email protected]> wrote:
> Yes. I just got back to looking at it and noticed the culprit was
> printString. Now #printString --> #printStringLimitedTo: -->
> #streamContents:limitedTo: which uses LimitedWriteStream that should
> protect against such recursion.
>
> However Array>>printOn: is...
>
> self shouldBePrintedAsLiteral ifTrue: [self printAsLiteralFormOn: aStream.
> ^ self].
> self isSelfEvaluating ifTrue: [self printAsSelfEvaluatingFormOn: aStream.
> ^ self].
> super printOn: aStream
>
> where #shouldBePrintedAsLiteral and #isSelfEvaluating recursively call
> themselves - bypassing the protection of LimitedWriteStream.
>
> As an aside, Array>>shouldBePrintedAsLiteral seems identical to
> Array>>isLiteral -- so is it redundant and the former be deprecated?
>
> Now I don't quite follow the semantics of #isLiteral and #isSelfEvaluating
> for Arrays.
>
> a := #( 1 2 { 3 . 4 } 5).
> a isLiteral. "true"
> a isSelfEvaluating. "true"
>
> b := { 1 . 2 . #( 3 4 ) . 5 }.
> b isLiteral. "true"
> b isSelfEvaluating. "true"
>
> So can someone provide an example for an Array where #isLiteral or
> #isSelfEvaluating are false ? Otherwise it seems it will always take
> the first condition of Array>>printOn: .
>
An Array that contains anything that isn't literal. e.g.
{1@2}
{1@2} isLiteral => false
{{1@2} size. #(1@2) size} => #(1 3)
> cheers -ben
>
> On Fri, Jan 30, 2015 at 9:23 PM, Nicolai Hess <[email protected]> wrote:
>
>> Quick and Dirty,
>> replace Array>>#printOn:
>> with
>>
>> printOn: aStream
>> self class = Array ifTrue: [self printAsSelfEvaluatingFormOn:
>> aStream. ^ self].
>> super printOn: aStream
>>
>> testObject := 'TEST'.
>> ref1 := { testObject. nil }.
>> ref2 := { ref1 }.
>> ref3 := { ref2 }.
>> ref1 at: 2 put: ref3. "note the reference loop this creates"
>> testObject pointersTo asString
>>
>> works
>>
>>
>> 2015-01-30 14:15 GMT+01:00 Nicolai Hess <[email protected]>:
>>
>>> Hi Ben,
>>>
>>> i don't know exactly what is happening here, but (size vs. inpsect)
>>>
>>> testObject := 'TEST'.
>>> ref1 := { testObject. nil }.
>>> ref2 := { ref1 }.
>>> ref3 := { ref2 }.
>>> ref1 at: 2 put: ref3. "note the reference loop this creates"
>>> testObject pointersTo size
>>> -> 5
>>>
>>>
>>>
>>> works. So, the problem is not in #pointersTo but inspecting the result
>>> array has one or more recursive self calls
>>> to its elements.
>>>
>>>
>>>
>>>
>>> 2015-01-30 3:59 GMT+01:00 Ben Coman <[email protected]>:
>>>
>>>>
>>>> I am revisiting my PointerDetective tool, which relies heavily on
>>>> ProtoObject>>pointersTo.
>>>>
>>>> The example I recorded at the repository home page is currently locking
>>>> & crashing the image due to #pointersTo being unable to handle the circular
>>>> reference. This "must" have been working on Windows at least around August
>>>> 2014, but I've been unable to reproduce a working case since my Windows
>>>> laptop died and I've since moved to OSX.
>>>>
>>>> On OSX, in a fresh image 40467 and latest vm 402, the following crashes
>>>> the image...
>>>>
>>>> testObject := 'TEST'.
>>>> ref1 := { testObject. nil }.
>>>> ref2 := { ref1 }.
>>>> ref3 := { ref2 }.
>>>> ref1 at: 2 put: ref3. "note the reference loop this creates"
>>>> testObject pointersTo inspect.
>>>>
>>>> OSX Memory Monitor shows memory usage shoot from 50MB to >500MB in a
>>>> few seconds, then usually the image crashes, but sometimes just hangs.
>>>>
>>>> I've logged...
>>>> https://pharo.fogbugz.com/default.asp?14827
>>>>
>>>> cheers -ben
>>>>
>>>>
>>>
>>
>
--
best,
Eliot