Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash by initialize() of CombinedChartView #406

Closed
venice81 opened this issue Sep 22, 2015 · 20 comments
Closed

Crash by initialize() of CombinedChartView #406

venice81 opened this issue Sep 22, 2015 · 20 comments
Labels

Comments

@venice81
Copy link

I don't speak English well.

CombinedChartView.initialize() -> () (CombinedChartView.swift:40)
CombinedChartView.initialize() -> () (CombinedChartView.swift:40)
ChartViewBase.init(frame : CGRect) -> ChartViewBase (ChartViewBase.swift:145)
BarLineChartViewBase.init(frame : CGRect) -> BarLineChartViewBase (BarLineChartViewBase.swift:75)
@objc CombinedChartView.init(frame : CGRect) -> CombinedChartView (CombinedChartView.swift:0)
-PDNoteBMIChangeWeightDetailView setupChartView

I found suspicious part in BarLineChartFillFormatter : 1650

private weak var _chart: BarLineChartViewBase!

I erased the 'weak'. so it's not crash anymore.
What right have I modified the way?

@liuxuan30
Copy link
Member

First, you should not delete 'weak', it is supposed to be weak I think.

I checked getFillLinePosition, it only has a function getFillLinePosition.

        let filled = generateFilledPath(
            entries,
            fillMin: delegate!.lineChartRendererFillFormatter(self).getFillLinePosition(
                dataSet: dataSet,
                data: delegate!.lineChartRendererData(self),
                chartMaxY: delegate!.lineChartRendererChartYMax(self),
                chartMinY: delegate!.lineChartRendererChartYMin(self)),
            from: minx,
            to: maxx,
            matrix: trans.valueToPixelMatrix)

So start from here.

Next time you see a crash, remember to post the back trace here, with the top most ones, that can be used to identify the issue.

@KerryJava
Copy link

  • thread Add a Bitdeli Badge to README #1: tid = 0x310af2, 0x00000001022368ef gpxj`gpxj.CombinedChartView.initialize (self=0x00007fcf385e4fb0)() -> () + 207 at CombinedChartView.swift:40, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    • frame #0: 0x00000001022368ef gpxjgpxj.CombinedChartView.initialize (self=0x00007fcf385e4fb0)() -> () + 207 at CombinedChartView.swift:40 [opt] frame #1: 0x00000001021c5245 gpxjgpxj.ChartViewBase.init (self=)(frame : C.CGRect) -> gpxj.ChartViewBase + 1141 at ChartViewBase.swift:145 [opt]
      frame Command failed due to signal: Segmentation fault: 11 #2: 0x0000000102193231 gpxjgpxj.BarLineChartViewBase.init (self=0x00007fcf385e4fb0)(frame : C.CGRect) -> gpxj.BarLineChartViewBase + 673 at BarLineChartViewBase.swift:74 [opt] frame #3: 0x000000010223a006 gpxj@objc gpxj.CombinedChartView.init (gpxj.CombinedChartView.Type)(frame : C.CGRect) -> gpxj.CombinedChartView [inlined] gpxj.CombinedChartView.init (gpxj.CombinedChartView.Type)(frame : C.CGRect) -> gpxj.CombinedChartView + 54 at CombinedChartView.swift:0 [opt]
      frame Cocoapod #4: 0x0000000102239fe3 gpxj`@objc gpxj.CombinedChartView.init (gpxj.CombinedChartView.Type)(frame : C.CGRect) -> gpxj.CombinedChartView + 19 at CombinedChartView.swift:0 [opt]

I met the same problem , XCode7 swift 2.0

@joseprl89
Copy link

Same here, oddly enough on debug mode it works fine.

@KerryJava
Copy link

I find the solution, CombinedChartView.swift,

    public override func initialize()
    {
        super.initialize()

        _fillFormatter = BarLineChartFillFormatter(chart: self)

        renderer = CombinedChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler)
    } 

changed to following

    public override func initialize()
    {
        super.initialize()
        let format = BarLineChartFillFormatter(chart: self)
         _fillFormatter = format
        renderer = CombinedChartRenderer(chart: self, animator: _animator, viewPortHandler: _viewPortHandler)
    } 

@liuxuan30
Copy link
Member

@KerryJava I have checked the code, _fillFormatter = BarLineChartFillFormatter(chart: self) was checked in on Jun, 30.

I have been using combined chart view all the time, and never see it crash here. Even now, I test it with ChartsDemo's combined chart view, no matter I change the optimization level from none to fast and fast whole module optimization, it also works fine, my setup is Xcode 7 + swift 2.0 + iOS 9. I also have released app, does not crash at all.

So, we need more info here, is it always crash on your side or how often? What's the configuration, like swift optimization level, Xcode, iOS version?

BTW, _fillFormatter is internal var, create a constant and assign to variable is dangerous.

@pappzsolt100
Copy link

I'm getting a very same crash after appstore upload. If I build for device or simulator from xcode it works fine. My crash is:

Crashed: com.apple.main-thread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x0000000000000ec0
Thread : Crashed: com.apple.main-thread
0 Charts 0x00000001008c5bc0 CombinedChartView.initialize() -> () (CombinedChartView.swift:40)
1 Charts 0x00000001008427d4 ChartViewBase.init(coder : NSCoder) -> ChartViewBase? (ChartViewBase.swift:151)
2 Charts 0x000000010085c934 BarLineChartViewBase.init(coder : NSCoder) -> BarLineChartViewBase? (BarLineChartViewBase.swift:79)
3 Charts 0x00000001008c9924 @objc CombinedChartView.init(coder : NSCoder) -> CombinedChartView? (CombinedChartView.swift)
4 UIKit 0x000000018ae52cb8 -[UIClassSwapper initWithCoder:] + 248
5 UIKit 0x000000018af67bf0 UINibDecoderDecodeObjectForValue + 672
6 UIKit 0x000000018af67d68 UINibDecoderDecodeObjectForValue + 1048
7 UIKit 0x000000018af67938 -[UINibDecoder decodeObjectForKey:] + 336
...

The code optimalization is turned off. Xcode Version 7.0 (7A220), Swift 2.0, iOS 8 - iOS 9

@KerryJava
Copy link

@liuxuan30 , It crash every time , so if it were configuration problem , why I make code changed like that can avoid crash problem ?

I try to user keyword 'var' , but the complier recommend using 'let'.

I can reproduce the problem using demo project. demo project works fine on my mac , if I remove the charts.xcproject and drag back again , it crash when it runs.

Chinese, demo工程没有问题,但是我重新手动配置就会复现这个问题。可以直接联系我啊,我的邮件是qq471723562@126.com

@liuxuan30
Copy link
Member

@KerryJava It's quite interesting, since I never crashed like this on my side. And a few people are having the same issue here. That's what we need to dig deeper, and find out the difference. My app needs to support iOS 7, so I simply drag all the swift files into my project and start from there. Are you using the framework directly? Will this matter?

I have tried with ChartsDemo, remove reference for charts.xcproject, and drag it back, on iOS simulator 9 and iPhone 6 plus model, nothing crashes for combined chart, debug mode.

@danielgindi, have you seen this or any ideas?

@cooler333
Copy link

Error raise only in release mode. In Debug mode all right. Just set build configuration in scheme to Release and exception will be raised :)

@pappzsolt100
Copy link

I've found a solution. I don't know why and also is it the right solution, but if I just drag and drop the .swift files in the project everything works fine. If I use embedded framework the release build crash every time...

@liuxuan30
Copy link
Member

@pappzsolt100 that is exactly why I don't see such issue, I need to support iOS 7. I am able to reproduce, still trying to figure out what's the problem.

@liuxuan30
Copy link
Member

I got this error message from console:

Charts was compiled with optimization - stepping may behave oddly; variables may not be available.

Looks like it has something to do with the release flag, the compiler is optimzing the code but has bugs.

I think this also can explain, why @KerryJava use

        let format = BarLineChartFillFormatter(chart: self)
         _fillFormatter = format

can clean the crash is that the compiler optimized in another way and avoid the crash.

So either use the files or add above code to workaround it. @danielgindi would you think accept above code?

@liuxuan30
Copy link
Member

did some more debugging:
assambly when crash:

    0x1001c8954 <+200>: bl     0x100176e60               ; type metadata accessor for Charts.BarLineChartFillFormatter
    0x1001c8958 <+204>: mov    x1, x0
    0x1001c895c <+208>: mov    x0, x19
    0x1001c8960 <+212>: bl     0x100172048               ; Charts.BarLineChartFillFormatter.__allocating_init (Charts.BarLineChartFillFormatter.Type)(chart : Charts.BarLineChartViewBase) -> Charts.BarLineChartFillFormatter at BarLineChartViewBase.swift
    0x1001c8964 <+216>: mov    x20, x0
    0x1001c8968 <+220>: ldr    x8, [x19]
    0x1001c896c <+224>: ldr    x9, [x23]
    0x1001c8970 <+228>: and    x8, x9, x8
->  0x1001c8974 <+232>: ldr    x21, [x8, #3752]
    0x1001c8978 <+236>: mov    x0, x19
    0x1001c897c <+240>: bl     0x1001e1a3c               ; symbol stub for: objc_retain

and check x8:

(lldb) reg read $x8
      x8 = 0x0000000000000000

Look at the crash reason:

* thread #1: tid = 0xe1284, 0x00000001001c8974 Charts`Charts.CombinedChartView.initialize (self=0x000000013ddc5eb0)() -> () + 232 at CombinedChartView.swift:43, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xea8)

address=0xea8 is exactly [x8, #3752] I think..

Continue to figure out why $x8 is nil:

    0x1001c8968 <+220>: ldr    x8, [x19]

now check x19:

(lldb) reg read x19
     x19 = 0x000000013ddc5eb0
(lldb) mem read $x19
0x13ddc5eb0: 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 10  ................
0x13ddc5ec0: 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  <.

and $x19 is exactly self's address:
self

Not sure if I am correct but looks like the compiler tried to read a wrong mem address. The reason is [$x19] has nothing at that moment, and computes a invalid mem address

But this actually somewhat explained:
Charts was compiled with optimization - stepping may behave oddly; variables may not be available.

@KerryJava
Copy link

    frame #1: 0x00000001026f3235 gpxj`gpxj.ChartViewBase.init (self=<unavailable>)(frame : C.CGRect) -> gpxj.ChartViewBase + 1141 at ChartViewBase.swift:145
    frame #2: 0x00000001026c1221 gpxj`gpxj.BarLineChartViewBase.init (self=0x00007fe79d8d39a0)(frame : C.CGRect) -> gpxj.BarLineChartViewBase + 673 at BarLineChartViewBase.swift:74

self= show everything

@pmairoldi
Copy link
Collaborator

I've seen the Charts was compiled with optimization - stepping may behave oddly; variables may not be available. error but it was easily fixable for me.

Don't know if its the same issue but I had a ChartDataSet with an empty array of ChartDataEntry which caused this issue. I just added a check for the the count and if they count is greater than 0 then I add it to the dataSets. Otherwise I just skip it.

I don't remember where it would crash but it wasn't where I was setting the data so it was hard to track. Maybe try what I did and see if that fixes the issue.

@liuxuan30
Copy link
Member

@petester42 , just like @cooler333 said, simply change the Run scheme's debug mode to release mode, and open the ChartsDemo's combined chart, it will crash the same way. So I am still guessing it's because of the compiler's optimization.

@danielgindi
Copy link
Collaborator

I cannot avoid committing the fix into master, as Xcode 7.0 is not in beta anymore, and a fix is not expected anytime soon.

The compiler bug was reported to Apple..... Let's see when a compiler fix will be issued...

@danielgindi
Copy link
Collaborator

Thank you guys for your efforts!

@liuxuan30 you've provided a lot of information regarding the issue,
@venice81 your solution seems to be the only one which produces correct assembly code.

The problem is not in the assignment, it seems, but in reading the pointer to the new variable.

When trying to assign through self.fillFormatter = ... it still fails on the same line, before stepping into setter of fillFormatter, and with the same assembly instructions. But when just assigning first to a let variable - it produces correct code.

@liuxuan30
Copy link
Member

@danielgindi One interesting thing is that I don't see this problem on my side, seems because I need to support iOS 7.0. I use source files and archive my app, which is also a release mode right? I am wondering why using source files has no problem.

@KerryJava
Copy link

@danielgindi a little correction , is my solution , not @venice81 's solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants