Label is retained in memory when bound to a shared FormattedString
- Dominant language
- C#
- Stars
- 23.3k
- Forks
- 2k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 290
Description
### Description
When a Label is assigned a shared or long-lived FormattedString (for example, from `App.Resources` or a view model), the Label is not garbage collected after it becomes unreachable.
### Expected Behavior:
A Label should be eligible for garbage collection once there are no remaining application references to it, even if the assigned FormattedString is shared or long-lived.
### Actual Behavior:
The Label remains alive because the shared FormattedString continues to hold strong event subscriptions to it, resulting in a memory leak.
### Steps to Reproduce:
1. Create a shared or long-lived FormattedString.
2. Add one or more Span objects to the FormattedString.
3. Create a Label and assign the shared FormattedString to its FormattedText property.
4. Remove all application references to the Label so it becomes unreachable.
5. Force garbage collection.
6. Observe that the Label is not garbage collected because it is still referenced by the shared FormattedString through strong event subscriptions.
```[Fact, Category(TestCategory.Memory)]
public async Task LabelIsNotKeptAliveBySharedFormattedText()
{
var formattedString = new FormattedString();
formattedString.Spans.Add(new Span { Text = "Hello" });
WeakReference CreateReference()
{
var label = new Label { FormattedText = formattedString };
return new(label);
}
WeakReference reference = CreateReference();
await TestHelpers.Collect();
Assert.False(await reference.WaitForCollect(), "Label should not be alive!");
// Ensure the shared FormattedString isn't collected during the test
GC.KeepAlive(formattedString);
}
Contributor guide
Research direction
Start with the LabelIsNotKeptAliveBySharedFormattedText test shown in the issue and run it with the memory-test category. Trace how Label assigns the shared FormattedString and how Span or FormattedString event subscriptions are removed. Done means the test observes that the Label is collected while the shared FormattedString remains alive.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 72/100