Charts: Crash on PieChartRenderer line 833

Created on 18 May 2019  路  5Comments  路  Source: danielgindi/Charts

What did you do?

I'm seeing two crash reports failing on the same line of PieChartRenderer from different users with different devices. This could be memory or timing-related, and I'm writing in the hopes that we can either find a way to replicate this issue or wrap defensive code around the line that's crashing.

What did you expect to happen?

I'd like PieChartView to do safety-checks before unsafe array operations to prevent hard-crashes. Even in case of misconfiguration, error logs would be preferred over hard crashes.

What happened instead?

Hard crash. Stack trace below.

Charts Environment

Charts version/Branch/Commit Number: v3.3.0
Xcode version: 10.2.1 (10E1001)
Swift version: 5
Platform(s) running Charts: 12.2.0 (16E227)
macOS version running Xcode: 10.14.4 (18E226)

Suggested workaround

Add a defensive if statement around the following unsafe insert:

PieChartRenderer.swift:833

accessibleChartElements.insert(contentsOf: highlightedAccessibleElements, at: 1)

Pull request: https://github.com/danielgindi/Charts/pull/4006

Stack Trace

#0. Crashed: com.apple.main-thread
0  Charts                         0x10084d6a8 specialized Array.replaceSubrange<A>(_:with:) (<compiler-generated>)
1  Charts                         0x10084b890 PieChartRenderer.drawHighlighted(context:indices:) (PieChartRenderer.swift:883)
2  Charts                         0x10078c738 PieChartView.draw(_:) (PieChartView.swift:110)
3  Charts                         0x10078caa4 @objc PieChartView.draw(_:) (<compiler-generated>)
4  UIKitCore                      0x1e479d44c -[UIView(CALayerDelegate) drawLayer:inContext:] + 476
5  (Missing)                      0x693b01bb93bfd8 (Missing)

Relevant Project Code

For the sake of completeness, I'm including all of my project code that interacts with Charts below. This code seems to work fine during testing and I'm unable to replicate the crash, leading me to believe the underlying problem related to environment conditions such as low memory. Crash reports also seem to indicate that the devices that crashed were low on memory at the time.

import UIKit
import Charts

class MyView: UIView {
  var holeRadiusPercent: CGFloat = 0.8
  var weights: [Double] = []
  var colors: [UIColor] = []

  override func awakeFromNib() {
        super.awakeFromNib()
        pieChartView = makePieChartView()
        addSubview(pieChartView)
        pieChartView.translatesAutoresizingMaskIntoConstraints = false
        pieChartView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        pieChartView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
        pieChartView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        pieChartView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        pieChartView.holeRadiusPercent = holeRadiusPercent
        if weights != nil && colors != nil {
            pieChartView.data = makePieChartData(
                currentWeights: weights,
                colors: colors
            )
        }
      }

  func makePieChartView() -> PieChartView {
      let pieChartView = PieChartView()
      pieChartView.drawEntryLabelsEnabled = false
      pieChartView.transparentCircleRadiusPercent = 0
      pieChartView.legend.enabled = false
      pieChartView.chartDescription?.enabled = false
      pieChartView.rotationEnabled = false
      pieChartView.holeColor = .clear
      return pieChartView
  }

  func makePieChartData(currentWeights: [Double], colors: [UIColor]) -> PieChartData {
      let entries = currentWeights.map { PieChartDataEntry(value: $0, label: nil) }
      let pieChartDataSet = PieChartDataSet(entries: entries, label: nil)
      pieChartDataSet.colors = colors
      pieChartDataSet.sliceSpace = sliceSpace
      pieChartDataSet.drawValuesEnabled = false
      pieChartDataSet.selectionShift = 0
      return PieChartData(dataSets: [pieChartDataSet])
  }
}

All 5 comments

hi i'm also having this issue when using version 3.3.0
but i'm using it as an dependency from react-native-charts-wrapper

accessibleChartElements.insert(contentsOf: highlightedAccessibleElements, at: 1)
Thread 1: Fatal error: Array replace: subrange extends past the end

@username199327 I submitted a PR to hopefully work around this issue:

https://github.com/danielgindi/Charts/pull/4006

If you're able to replicate this bug consistently, I'd love to retrace your steps and confirm the PR works.

The best evidence I currently have to identify the underlying cause is that all the crashed devices were low on memory at the time. Specifically at 2% - 3% free RAM.

Thanks! But have to wait a few days - really busy recently. Have to understand what's wrong first

@username199327 I submitted a PR to hopefully work around this issue:

4006

If you're able to replicate this bug consistently, I'd love to retrace your steps and confirm the PR works.

The best evidence I currently have to identify the underlying cause is that all the crashed devices were low on memory at the time. Specifically at 2% - 3% free RAM.

i have no idea on how to fully replicate it, but i manage to avoid it maybe?
on my end it's because the previous data is still present event though the view has been closed, and when re-opened it will take the previous data and then replace it with new data
on the process of replacing them, that's what caused the crash on my end

Fixed in latest commit. Marking closed.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ahmedsafadii picture ahmedsafadii  路  3Comments

brytnvmg picture brytnvmg  路  4Comments

kirti0525 picture kirti0525  路  3Comments

coop44483 picture coop44483  路  3Comments

Bharati555 picture Bharati555  路  4Comments