iOS Swift - Remove last method from stacktrace - ios

I have a utility method for logging various non-fatal errors in my project. In this method I also send the error to Crashlytics by its record() method, but when looking at Crashlytics, all errors are grouped together into one instance, beacause the last info in the stacktrace is line x of my UtilityClass (where Crashlytics.crashlytics().record(error: error) is called).
Can I remove from the stacktrace the reference about the last method before calling Crashlytics.crashlytics().record(error: error)? And how to do it?
There are other ways?
I'm looking for a way to tell Crashlytics that all my non-fatal events are not coming from the same line of code, but from the line that calls that line, so that all the events are not grouped togheter.

In general, the crashes will be grouped together based on the highlighted blamed frame and not necessarily by the top frame in the stack trace. This means that crashes with different stack traces could end up in the same issue if the same frame is blamed on both.
This is what I mean by blamed frame:
If the latest frame is related to your utility method and that is the one being framed, expanding on what you mentioned in the comment about using the ExceptionModel, I came up with this workaround:
var exMod = ExceptionModel.init(name: NSURLErrorDomain, reason: "some reason")
var stack: [StackFrame] = [];
// The current stack trace is obtained after removing the first element
for frame in Thread.callStackSymbols.dropFirst(){
// The frame is a String, the address value is obtained and appended to the stack array.
let frameArray = frame.description.split(separator: " ");
// The address is a String and is converted to a UInt value
let address = UInt(frameArray[2].dropFirst(2), radix: 16) ?? 0
stack.append(StackFrame(address: address));
}
// The stack trace is added to the ExceptionModel
exMod.stackTrace = stack;
Crashlytics.crashlytics().record(exceptionModel: exMod)
This is the result of running this snippet without “.dropFirst()”:
And this is the result dropping the first element:
As you can see, the first element was removed as expected.
My suggestion would be to first try causing different crashes on different parts of your app and see if the same frame is getting blamed. I.e: Checking if those crashes keep getting grouped.
Then check if the above snippet works for your use case.

Related

Where does a segmentation fault occur if the debugger points to a function definition?

To elaborate, I am currently writing a program that requires a function that is provided by the professor. When I run the program, I get a segmentation fault, and the debugger I use (gdb) says that the segmentation fault occurred at the definition of the function that, like I said, was provided by the professor.
So my question here is, is the definition itself causing the fault, or is it somewhere else in the program that called the function causing the fault?
I attempted to find a spot in the program that might have been leading to it, such as areas that might have incorrect parameters. I have not changed the function itself, as it is not supposed to be modified (as per instructions). This is my first time posting a question, so if there is any other information needed, please let me know.
The error thrown is as follows:
Program received signal SIGSEGV, Segmentation fault. .0x00401450 in Parser::GetNextToken (in=..., line=#0x63fef0: 1) at PA2.cpp:20 20 return GetNextToken(in, line);
The code itself that this is happening at is this:
static LexItem GetNextToken(istream& in, int& line) {
if( pushed_back ) {
pushed_back = false;
return pushed_token;
}
return GetNextToken(in, line);
}
Making many assumptions here, but maybe the lesson is to understand how the stack is affected by a function call and parameters. Create a main() function, that call the professor's provided function and trace the code using dbg, looking at the stack.

AddressSanitizer: heap-use-after-free only on Release archive

I have created an example of my class: https://github.com/ChoadPet/H.264-Decoding
When I build my application with DEBUG configuration everything is working fine, but when I archive RELEASE it's crashing on this line:
let status = VTDecompressionSessionDecodeFrame(session,
sampleBuffer: sampleBuffer,
flags: defaultDecodeFlags,
frameRefcon: nil,
infoFlagsOut: nil)
With Address Sanitizer enable I got this error:
Thread 9: Use of deallocated memory
SUMMARY: AddressSanitizer: heap-use-after-free
(.../Frameworks/libclang_rt.asan_ios_dynamic.dylib:arm64+0x1a1f4) in wrap_memmove
...
(if you need more crash info, let me know)
Without: Thread 12: EXC_BAD_ACCESS (code=1, address=0x107dd0020)
I do understand that there is some memory that was freed and it accesses by VTDecompressionSessionDecodeFrame method, but I can't find any address with hex, and I don't understand how this is working perfectly with the DEBUG build.
Before this method, session and sampleBuffer are successfully created(initialized).
Is there are some project settings I can change to DEBUG configuration which can cause the crash? Or somebody can point me out on a code issue?
Thank you!
Changing Optimization Level for Release archive to the same as for Debug - No Optimization[-Onone] hide the problem, but changing build configuration is not the right way to resolve this kinda problem. Also, the problem was not exactly in sampleBuffer. The problem was in blockBufferOut parameter, which goes into sampleBuffer later. I will update the repo source code, so the community can see changes clearly.
So I had before this logic:
// 1. Creating blockBuffer from `bufferPointer`
localFrame.withUnsafeMutableBufferPointer { bufferPointer in
// I should write everything in this body,
// since bufferPointer would be released after the closure
// and so, it will be released from bufferBlock
}
// 2. I called this method, which is creating `sampleBuffer`
CMSampleBufferCreateReady
// 3. I called this method, which is decode frame with session and sampleBuffer
VTDecompressionSessionDecodeFrame
/*
and on this line, it crashes with EXC_BAD_ACCESS,
because the sample wasn't valid anymore, because
on step 1, bufferPointer only valid inside body closure,
so it's release after block when I created sampleBuffer
and later decode it.
This is even pointed by documentation:
Parameters
body
Closure with an UnsafeMutableBufferPointer parameter that points to the
contiguous storage for the array. If no such storage exists, it is created. If
the body has a return value, that value is also used as the return value for the
withUnsafeMutableBufferPointer(_:) method. The pointer argument is valid only for
the duration of the method’s execution.
*/
Summary: if you operate on bufferPointer, do all operations inside a closure.
Added to the answer provided by #vpoltave, I found using a dispatch queue after the samplebuffer creation used to give me an EXC_BAD_ACCESS error or if you turn on address sanitiser, then it would error out in the com.apple.coremedia.videomediaconverter with Use of deallocated memory. Suggestion is to enqueue the raw data instead of the created buffers. For me the source was a frame in elementary format coming in callbacks.

Crashlytics iOS - Crash at line 0 - Swift sources

I'm currently facing a problem with some Swift source files when a crash occurs. Indeed, on Crashlytics I have a weird info about the line and the reason of the crash. It tells me the source has crashed at the line 0 and it gives me a SIGTRAP error. I read that this error occurs when a Thread hits a BreakPoint. But the problem is that this error occurs while I'm not debugging (application test from TestFlight).
Here is an example when Crashlytics tells me there's a SIGTRAP Error at line 0 :
// Method that crashs
private func extractSubDataFrom(writeBuffer: inout Data, chunkSize: Int) -> Data? {
guard chunkSize > 0 else { // Prevent from having a 0 division
return nil
}
// Get nb of chunks to write (then the number of bytes from it)
let nbOfChunksToWrite: Int = Int(floor(Double(writeBuffer.count) / Double(chunkSize)))
let dataCountToWrite = max(0, nbOfChunksToWrite * chunkSize)
guard dataCountToWrite > 0 else {
return nil // Not enough data to write for now
}
// Extract data
let subData = writeBuffer.extractSubDataWith(range: 0..<dataCountToWrite)
return subData
}
Another Swift file to explain what happens at the line "writeBuffer.extractSubDataWith(range: 0..
public extension Data {
//MARK: - Public
public mutating func extractSubDataWith(range: Range) -> Data? {
guard range.lowerBound >= 0 && range.upperBound <= self.count else {
return nil
}
// Get a copy of data and remove them from self
let subData = self.subdata(in: range)
self.removeSubrange(range)
return subData
}
}
Could you tell me what I'm doing wrong ? Or what can occurs this weird SIGTRAP error ?
Thank you
Crashing with a line of zero is indeed weird. But, common in Swift code.
The Swift compiler can do code generation on your behalf. This can happen quite a bit with generic functions, but may also happen for other reasons. When the compiler generates code, it also produces debug information for the code it generates. This debug information typically references the file that caused the code to be generated. But, the compiler tags it all with a line of 0 to distinguish it from code that was actually written by the developer.
These generic functions also do not have to be written by you - I've seen this happen with standard library functions too.
(Aside: I believe that the DWARF standard can, in fact, describe this situation more precisely. But, unfortunately Apple doesn't seem to use it in that way.)
Apple verified this line zero behavior via a Radar I filed about it a number of years ago. You can also poke around in your app's own debug data (via, for example dwarfdump) if you want to confirm.
One reason you might want to try to do this, is if you really don't trust that Crashlytics is labelling the lines correctly. There's a lot of stuff between their UI and the raw crash data. It is conceivable something's gone wrong. The only way you can confirm this is to grab the crashing address + binary, and do the lookup yourself. If dwarfdump tells you this happened at line zero, then that confirms this is just an artifact of compile-time code generation.
However, I would tend to believe there's nothing wrong with the Crashlytics UI. I just wanted to point it out as a possibility.
As for SIGTRAP - there's nothing weird about that at all. This is just an indication that the code being run has decided to terminate the process. This is different, for example, from a SIGBUS, where the OS does the terminating. This could be caused by Swift integer and/or range bounds checking. Your code does have some of that kind of thing in both places. And, since that would be so performance-critical - would be a prime candidate for inline code generation.
Update
It now seems like, at least in some situations, the compiler also now uses a file name of <compiler-generated>. I'm sure they did this to make this case clearer. So, it could be that with more recent versions of Swift, you'll instead see <compiler-generated>:0. This might not help tracking down a crash, but will least make things more obvious.

Scope of causes for EXC_BREAKPOINT crash

I have this stack trace in Fabric:
My question: From the crash log, is the function 'formatMessageAuthorName' the only cause for this EXC_BREAKPOINT crash? E.g., are there other possible causes for the crash apart from the code inside this function?
Here is my formatMessageAuthorName function:
private static func formatMessageAuthorName(firstname: String, lastname: String?=nil) -> String {
// Capitalise first character of firstname
var Cap_firstname = firstname
Cap_firstname.replaceRange(Cap_firstname.startIndex...Cap_firstname.startIndex, with: String(Cap_firstname[Cap_firstname.startIndex]).capitalizedString)
guard let lastname = lastname else { return Cap_firstname }
// if has lastname & first char, capitalise too and concat with firstname.
if let firstCharLastName = lastname.characters.first {
return "\(Cap_firstname) \(String(firstCharLastName).uppercaseString)."
} else {
return firstname
}
}
My assumption
The only clue that I know that will make the function crash is when 'firstname' is an empty string, it will crash here since it accesses invalid array index:
String(Cap_firstname[Cap_firstname.startIndex])
However, I'm still skeptical about this assumption, since I'm quite sure that 'firstname' is not empty (it's retrieved from server). I even tested it by logging into some user accounts that has this crash, and using that page (MessageViewController), but I never had the crash myself and firstname is shown correctly. It also seems to not be about iOS versions as I received crash from iOS 8, 9, and 10.
I have this crash a lot (>300) after my recent app update and I have no idea why as it never happens before, the code here does not change through the update, and I can never reproduce it with the effected users.
If the culprit can only be the code in this function, and no other possibilities (like multi-threading, Realm etc.), I can turn to focus on the server issues instead, like how 'firstname' might be an empty string. But still, I can't imagine how it could happen, since I already used those user accounts and never have this crash myself.
Thanks a lot.
EXC_BREAKPOINT is always triggered by executing a trap instruction of some sort(*) and the exception gets delivered directly to the thread that executed the trap instruction. So if you are seeing a crash report that says this thread with this stack got an EXC_BREAKPOINT, that means that thread really did to something that executed a trap instruction.
You could probably see this by looking at the crash address in your binary, you will see some kind of trap instruction there. The swift standard library uses trap instructions to signal various kinds of invalid access errors, and that code probably got inlined into the function that's crashing. So this makes sense of your example above.
(*) EXC_BREAKPOINT can also be used for data watches, but that's not what's happening here, and anyway they would still be delivered to the thread that accessed the watched data...

thread 1 EXC_BREAKPOINT (code=1, subcode=0x101959bfc) Swift

I try to update my project to Swift 3 and my app crash just after launching Xcode display the following message:
thread 1 EXC_BREAKPOINT (code=1, subcode=0x101959bfc)
here's the line where the problem happened
var list:[PFObject]! = []
(...)
let x = list[indexPath.row - 1]
let text:Int = (x["text"] as! NSArray)[0] as! Int //The line where the error is displayed
The console only said that:
(lldb)
I've removed all the breakpoints from the breakpoints navigator with no result, the issue happened both on device and on simulator. (I use Xcode 8.2)
Thanks a lot for your help
Take a look at the stack trace printed right before (lldb), and break down that statement in smaller pieces if is still hard to understand where the error actually is.
Considering the line the pointer is at, it could be that x["text"] is not an array, that the array is empty, or that the element is not an int.
In other words, those force unwrap could fail or the array could be empty.

Resources