GithubHelp home page GithubHelp logo

facebook / fbretaincycledetector Goto Github PK

View Code? Open in Web Editor NEW
4.2K 107.0 575.0 2.99 MB

iOS library to help detecting retain cycles in runtime.

License: Other

Ruby 1.12% Objective-C 41.24% Objective-C++ 50.95% C 5.99% Shell 0.70%

fbretaincycledetector's Introduction

FBRetainCycleDetector

Support Ukraine Build Status Carthage compatible CocoaPods License

An iOS library that finds retain cycles using runtime analysis.

About

Retain cycles are one of the most common ways of creating memory leaks. It's incredibly easy to create a retain cycle, and tends to be hard to spot it. The goal of FBRetainCycleDetector is to help find retain cycles at runtime. The features of this project were influenced by Circle.

Installation

Carthage

To your Cartfile add:

github "facebook/FBRetainCycleDetector"

FBRetainCycleDetector is built out from non-debug builds, so when you want to test it, use

carthage update --configuration Debug

CocoaPods

To your podspec add:

pod 'FBRetainCycleDetector'

You'll be able to use FBRetainCycleDetector fully only in Debug builds. This is controlled by compilation flag that can be provided to the build to make it work in other configurations.

Example usage

Let's quickly dive in

#import <FBRetainCycleDetector/FBRetainCycleDetector.h>
FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:myObject];
NSSet *retainCycles = [detector findRetainCycles];
NSLog(@"%@", retainCycles);

- (NSSet<NSArray<FBObjectiveCGraphElement *> *> *)findRetainCycles will return a set of arrays of wrapped objects. It's pretty hard to look at at first, but let's go through it. Every array in this set will represent one retain cycle. Every element in this array is a wrapper around one object in this retain cycle. Check FBObjectiveCGraphElement.

Example output could look like this:

{(
    (
        "-> MyObject ",
        "-> _someObject -> __NSArrayI "
    )
)}

MyObject through someObject property retained NSArray that it was a part of.

FBRetainCycleDetector will look for cycles that are no longer than 10 objects. We can make it bigger (although it's going to be slower!).

FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:myObject];
NSSet *retainCycles = [detector findRetainCyclesWithMaxCycleLength:100];

Filters

There could also be retain cycles that we would like to omit. It's because not every retain cycle is a leak, and we might want to filter them out. To do so we need to specify filters:

NSMutableArray *filters = @[
  FBFilterBlockWithObjectIvarRelation([UIView class], @"_subviewCache"),
];

// Configuration object can describe filters as well as some options
FBObjectGraphConfiguration *configuration =
[[FBObjectGraphConfiguration alloc] initWithFilterBlocks:filters
                                     shouldInspectTimers:YES];
FBRetainCycleDetector *detector = [[FBRetainCycleDetector alloc] initWithConfiguration:configuration];
[detector addCandidate:myObject];
NSSet *retainCycles = [detector findRetainCycles];

Every filter is a block that having two FBObjectiveCGraphElement objects can say, if their relation is valid.

Check FBStandardGraphEdgeFilters to learn more about how to use filters.

NSTimer

NSTimer can be troublesome as it will retain it's target. Oftentimes it means a retain cycle. FBRetainCycleDetector can detect those, but if you want to skip them, you can specify that in the configuration you are passing to FBRetainCycleDetector.

FBObjectGraphConfiguration *configuration =
[[FBObjectGraphConfiguration alloc] initWithFilterBlocks:someFilters
                                     shouldInspectTimers:NO];
FBRetainCycleDetector *detector = [[FBRetainCycleDetector alloc] initWithConfiguration:configuration];

Associations

Objective-C let's us set associated objects for every object using objc_setAssociatedObject.

These associated objects can lead to retain cycles if we use retaining policies, like OBJC_ASSOCIATION_RETAIN_NONATOMIC. FBRetainCycleDetector can catch these kinds of cycles, but to do so we need to set it up. Early in the application's lifetime, preferably in main.m we can add this:

#import <FBRetainCycleDetector/FBAssociationManager.h>

int main(int argc, char * argv[]) {
  @autoreleasepool {
    [FBAssociationManager hook];
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
  }
}

In the code above [FBAssociationManager hook] will use fishhook to interpose functions objc_setAssociatedObject and objc_resetAssociatedObjects to track associations before they are made.

Getting Candidates

If you want to profile your app, you might want to have an abstraction over how to get candidates for FBRetainCycleDetector. While you can simply track it your own, you can also use FBAllocationTracker. It's a small tool we created that can help you track the objects. It offers simple API that you can query for example for all instances of given class, or all class names currently tracked, etc.

FBAllocationTracker and FBRetainCycleDetector can work nicely together. We have created a small example and drop-in project called FBMemoryProfiler that leverages both these projects. It offers you very basic UI that you can use to track all allocations and force retain cycle detection from UI.

Contributing

See the CONTRIBUTING file for how to help out.

License

FBRetainCycleDetector is BSD-licensed.

fbretaincycledetector's People

Contributors

aditya7fb avatar amonshiz avatar arj-fb avatar bcse avatar caodoan avatar chowarfb avatar cuva avatar dacaiguoguogmail avatar dmitryvinn avatar facebook-github-bot avatar johnhaitas avatar jspahrsummers avatar kastiglione avatar liuzhiyi1992 avatar maxovtsin avatar mboyd avatar megcanicalkb avatar mortonfox avatar nealyoung avatar rmaz avatar rs17b avatar tditchek avatar thegreatwallfb avatar ttsugriy avatar youngdfb avatar zhongwuzw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fbretaincycledetector's Issues

FBRetainCycleDetector Crashing

I have same issue.
I have Integrated FBMemory Profiler In our App till now it is good it shows Retain Cycles. Recently we have update to Swift 4.0 compiling Our App from Xcode 9.2 With FBMemoryProfiler when I'm Clicking on RetainCycle Button App is Crashing.

Questions about get block strong layout

Hi, currently I am reading source code of this lib. But some code in FBBlockStrongLayout.m really confuses me. How does this lib figure out which variable block can retain.

These lines of code are copied from _GetBlockStrongLayout function in FBBlockStrongLayout.m

  void (*dispose_helper)(void *src) = blockLiteral->descriptor->dispose_helper;
  const size_t ptrSize = sizeof(void *);

  // Figure out the number of pointers it takes to fill out the object, rounding up.
  const size_t elements = (blockLiteral->descriptor->size + ptrSize - 1) / ptrSize;

  // Create a fake object of the appropriate length.
  void *obj[elements];
  void *detectors[elements];

  for (size_t i = 0; i < elements; ++i) {
    FBBlockStrongRelationDetector *detector = [FBBlockStrongRelationDetector new];
    obj[i] = detectors[i] = detector;
  }

  @autoreleasepool {
    dispose_helper(obj);
  }

  // Run through the release detectors and add each one that got released to the object's
  // strong ivar layout.
  NSMutableIndexSet *layout = [NSMutableIndexSet indexSet];

  for (size_t i = 0; i < elements; ++i) {
    FBBlockStrongRelationDetector *detector = (FBBlockStrongRelationDetector *)(detectors[i]);
    if (detector.isStrong) {
      [layout addIndex:i];
    }

    // Destroy detectors
    [detector trueRelease];
  }

I'm quite confused about the dispose_helper here. Does the dispose_helper dealloc the objects that block retains according to their memory address? So we can fake an array of objects and use dispose_helper to dealloc our objects, and then we can find out which object of the array is not existed. So we can get indexed and retrieve all the objects which block has retained.

Thanks for your reading, and I really wanna know how this lib works. 😄

EXC_BAD_ACCESS

  • thread #7, queue = 'com.apm.leakers.serial.queue', stop reason = EXC_BAD_ACCESS (code=1, address=0x1)
    frame #0: 0x0000000105618397 libobjc.A.dylib`objc_retain + 7
    • frame #1: 0x0000000102a49744 XMAPM-[FBObjectiveCObject allRetainedObjects](self=0x00006000000ee5a0, _cmd="allRetainedObjects") at FBObjectiveCObject.m:90:74 frame #2: 0x0000000102a46478 XMAPM::-[FBNodeEnumerator nextObject](self=0x00006000000e8a20, _cmd="nextObject") at FBNodeEnumerator.mm:34:32
      frame #3: 0x0000000102a4b06c XMAPM::-[FBRetainCycleDetector _findRetainCyclesInObject:stackDepth:](self=0x00006000000191e0, _cmd="_findRetainCyclesInObject:stackDepth:", graphElement=0x00006000000e94e0, stackDepth=20) at FBRetainCycleDetector.mm:132:41 frame #4: 0x0000000102a4a40c XMAPM::-[FBRetainCycleDetector findRetainCyclesWithMaxCycleLength:](self=0x00006000000191e0, _cmd="findRetainCyclesWithMaxCycleLength:", length=20) at FBRetainCycleDetector.mm:65:66
      frame #5: 0x0000000102b05e64 XMAPM__39+[XMLeakedObjectProxy addLeakedObject:]_block_invoke(.block_descriptor=0x00006000015ca680) at XMLeakedObjectProxy.m:111:35 frame #6: 0x000000010863ddf0 libdispatch.dylib_dispatch_call_block_and_release + 12
      frame #7: 0x000000010863ed64 libdispatch.dylib_dispatch_client_callout + 8 frame #8: 0x000000010864560b libdispatch.dylib_dispatch_lane_serial_drain + 788
      frame #9: 0x000000010864619b libdispatch.dylib_dispatch_lane_invoke + 422 frame #10: 0x0000000108651a59 libdispatch.dylib_dispatch_workloop_worker_thread + 722
      frame #11: 0x00007fff5141c611 libsystem_pthread.dylib_pthread_wqthread + 421 frame #12: 0x00007fff5141c3fd libsystem_pthread.dylibstart_wqthread + 13

Cannot find any useful information

I have a complicated viewController, and I use this in function like this:

    FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
    [detector addCandidate:self];
    NSSet *retainCycles = [detector findRetainCycles];
    NSLog(@"%@", retainCycles);
    [self dismissViewControllerAnimated:YES completion:nil];

But the controller's dealloc function not called and I cannot find any useful information

{(
)}

array has incomplete element type 'struct rcd_rebinding'

hey there,when i import this library,appears the compile problem "array has incomplete element type 'struct rcd_rebinding'",i set the file name AppDelegate.mm and import libc++.tbd still can not fix this problem.any good suggestion ? thanks.

1

pod validation error

tried to integrate this lib as a pod.

but pod spec lint gives the following error

`he following build commands failed:
CompileC /var/folders/xy/9_l5r2r14cqg8dv46kn4c86w0000gp/T/CocoaPods/Lint/build/Pods.build/Release-iphonesimulator/FBRetainCycleDetector.build/Objects-normal/i386/FBObjectiveCGraphElement.o FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.m normal i386 objective-c com.apple.compilers.llvm.clang.1_0.compiler
(1 failure)
-> FBRetainCycleDetector (0.1.2)
- ERROR | [iOS] Returned an unsuccessful exit code.
- ERROR | [iOS] FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.m:21:1: error: cannot synthesize weak property in file using manual reference counting
- NOTE | [iOS] FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.h:41:42: note: property declared here

Analyzed 1 podspec.

[!] The spec did not pass validation, due to 2 errors.`

Questions about elements in FBBlockStrongLayout

in _GetBlockStrongLayout has these code, but why is it calculated like this? thx

  // Figure out the number of pointers it takes to fill out the object, rounding up.
  const size_t elements = (blockLiteral->descriptor->size + ptrSize - 1) / ptrSize;

Can't detect object in array

I had encountered one case, when a custom subview which retain the view controller was added to the view controller's view, FBRetainCycleDetector will not detect objects in the subview array.

FBRetainCycleDetector has a crash

(lldb) bt
FBRecycleTest was compiled with optimization - stepping may behave oddly; variables may not be available.

  • thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x8)
    frame #0: 0x00000001047cc527 libc++.1.dylib`std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >::basic_string(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&) + 27
    • frame #1: 0x000000010448f734 FBRecycleTestFB::RetainCycleDetector::Parser::Type::Type(this=0x000060c000127b38, name=<unavailable>, typeEncoding="{?=\"mutations\"Q}") at Type.h:25 [opt] frame #2: 0x000000010448fbc8 FBRecycleTestFB::RetainCycleDetector::Parser::Struct::Struct(this=0x000060c000127b38, name=, typeEncoding=, structTypeName="?", typesContainedInStruct=size=1) at Struct.h:27 [opt]
      frame #3: 0x000000010448f372 FBRecycleTeststd::__1::shared_ptr<FB::RetainCycleDetector::Parser::Struct> std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Struct>::make_shared<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type>, std::__1::allocator<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type> > >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&&&, std::__1::vector<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type>, std::__1::allocator<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type> > >&&&) [inlined] FB::RetainCycleDetector::Parser::Struct::Struct(this=<unavailable>, name="", typeEncoding="{?=\"mutations\"Q}", structTypeName="?", typesContainedInStruct=size=1) at Struct.h:29 [opt] frame #4: 0x000000010448f35c FBRecycleTeststd::__1::shared_ptrFB::RetainCycleDetector::Parser::Struct std::__1::shared_ptrFB::RetainCycleDetector::Parser::Struct::make_shared<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > >&>(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&&&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&&&, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > >&&&) [inlined] std::__1::__libcpp_compressed_pair_imp<std::__1::allocatorFB::RetainCycleDetector::Parser::Struct, FB::RetainCycleDetector::Parser::Struct, 1u>::__libcpp_compressed_pair_imp<std::__1::allocatorFB::RetainCycleDetector::Parser::Struct&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > >&, 0ul, 0ul, 1ul, 2ul, 3ul>(__second_args=tuple<std::__1::basic_string &, std::__1::basic_string &&, const std::__1::basic_string &, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > > &> @ 0x00007fdbae9c5840) at memory:2194 [opt]
      frame #5: 0x000000010448f355 FBRecycleTeststd::__1::shared_ptr<FB::RetainCycleDetector::Parser::Struct> std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Struct>::make_shared<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type>, std::__1::allocator<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type> > >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&&&, std::__1::vector<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type>, std::__1::allocator<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type> > >&&&) [inlined] std::__1::__compressed_pair<std::__1::allocator<FB::RetainCycleDetector::Parser::Struct>, FB::RetainCycleDetector::Parser::Struct>::__compressed_pair<std::__1::allocator<FB::RetainCycleDetector::Parser::Struct>&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type>, std::__1::allocator<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type> > >&>(__second_args=tuple<std::__1::basic_string<char> &, std::__1::basic_string<char> &&, const std::__1::basic_string<char> &, std::__1::vector<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type>, std::__1::allocator<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type> > > &> @ 0x00007fdbae9c5810) at memory:2457 [opt] frame #6: 0x000000010448f355 FBRecycleTeststd::__1::shared_ptrFB::RetainCycleDetector::Parser::Struct std::__1::shared_ptrFB::RetainCycleDetector::Parser::Struct::make_shared<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > >&>(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&&&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&&&, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > >&&&) [inlined] std::__1::__compressed_pair<std::__1::allocatorFB::RetainCycleDetector::Parser::Struct, FB::RetainCycleDetector::Parser::Struct>::__compressed_pair<std::__1::allocatorFB::RetainCycleDetector::Parser::Struct&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > >&>(__second_args=tuple<std::__1::basic_string &, std::__1::basic_string &&, const std::__1::basic_string &, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > > &> @ 0x00007fdbae9c5810) at memory:2460 [opt]
      frame #7: 0x000000010448f355 FBRecycleTeststd::__1::shared_ptr<FB::RetainCycleDetector::Parser::Struct> std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Struct>::make_shared<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type>, std::__1::allocator<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type> > >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&&&, std::__1::vector<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type>, std::__1::allocator<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type> > >&&&) [inlined] std::__1::__shared_ptr_emplace<FB::RetainCycleDetector::Parser::Struct, std::__1::allocator<FB::RetainCycleDetector::Parser::Struct> >::__shared_ptr_emplace<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type>, std::__1::allocator<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type> > >&>(__args="", __args="{?=\"mutations\"Q}", __args="?", __args=size=1) at memory:3800 [opt] frame #8: 0x000000010448f337 FBRecycleTeststd::__1::shared_ptrFB::RetainCycleDetector::Parser::Struct std::__1::shared_ptrFB::RetainCycleDetector::Parser::Struct::make_shared<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > >&>(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&&&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&&&, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > >&&&) [inlined] std::__1::__shared_ptr_emplace<FB::RetainCycleDetector::Parser::Struct, std::__1::allocatorFB::RetainCycleDetector::Parser::Struct >::__shared_ptr_emplace<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > >&>(__args="", __args="{?="mutations"Q}", __args="?", __args=size=1) at memory:3801 [opt]
      frame #9: 0x000000010448f337 FBRecycleTeststd::__1::shared_ptr<FB::RetainCycleDetector::Parser::Struct> std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Struct>::make_shared<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type>, std::__1::allocator<std::__1::shared_ptr<FB::RetainCycleDetector::Parser::Type> > >&>(__args=<unavailable>, __args=<unavailable>, __args=<unavailable>, __args=<unavailable>) at memory:4411 [opt] frame #10: 0x000000010448e803 FBRecycleTestFB::RetainCycleDetector::Parser::_ParseStructEncodingWithScanner((anonymous namespace)::_StringScanner&) [inlined] std::__1::enable_if<!(is_arrayFB::RetainCycleDetector::Parser::Struct::value), std::__1::shared_ptrFB::RetainCycleDetector::Parser::Struct >::type std::__1::make_shared<FB::RetainCycleDetector::Parser::Struct, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::vector<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type, std::__1::allocator<std::__1::shared_ptrFB::RetainCycleDetector::Parser::Type > >&>(__args="", __args="{?="mutations"Q}", __args=) at memory:4775 [opt]
      frame #11: 0x000000010448e7fe FBRecycleTestFB::RetainCycleDetector::Parser::_ParseStructEncodingWithScanner(scanner=<unavailable>)::_StringScanner&) at FBStructEncodingParser.mm:110 [opt] frame #12: 0x000000010448e240 FBRecycleTestFB::RetainCycleDetector::Parser::parseStructEncodingWithName(structEncodingString="{?="buffer"^@"state"(?=""{?="mutations"Q}""{?="muts"I"used"b25"kvo"b1"szidx"b6})}", structName="storage") at FBStructEncodingParser.mm:152 [opt]
      frame #13: 0x000000010448d2a5 FBRecycleTest::FBGetClassReferences(Class) [inlined] FBGetReferencesForObjectsInStructEncoding(ivar=0x000060c000246960, encoding=<unavailable>) at FBClassStrongLayout.mm:33 [opt] frame #14: 0x000000010448d1f6 FBRecycleTest::FBGetClassReferences(aCls=) at FBClassStrongLayout.mm:109 [opt]
      frame #15: 0x000000010448d9e1 FBRecycleTest::FBGetObjectStrongReferences(id, NSMutableDictionary *) [inlined] FBGetStrongReferencesForClass(objc_class*) at FBClassStrongLayout.mm:159 [opt] frame #16: 0x000000010448d9d6 FBRecycleTest::FBGetObjectStrongReferences(obj=, layoutCache=) at FBClassStrongLayout.mm:200 [opt]
      frame #17: 0x0000000104490ed1 FBRecycleTest-[FBObjectiveCObject allRetainedObjects](self=<unavailable>, _cmd=<unavailable>) at FBObjectiveCObject.m:28 [opt] frame #18: 0x000000010448cd93 FBRecycleTest::-[FBNodeEnumerator nextObject](self=0x000060c000224ee0, _cmd=) at FBNodeEnumerator.mm:34 [opt]
      frame #19: 0x000000010448b1be FBRecycleTest::-[FBRetainCycleDetector _findRetainCyclesInObject:stackDepth:](self=0x000060c0002247c0, _cmd=<unavailable>, graphElement=<unavailable>, stackDepth=10) at FBRetainCycleDetector.mm:102 [opt] frame #20: 0x000000010448af05 FBRecycleTest::-[FBRetainCycleDetector findRetainCyclesWithMaxCycleLength:](self=0x000060c0002247c0, _cmd=, length=10) at FBRetainCycleDetector.mm:63 [opt]
      frame #21: 0x000000010448855e FBRecycleTest-[ViewController viewWillAppear:](self=0x00007fe80dd0cd40, _cmd="viewWillAppear:", animated=YES) at ViewController.m:60 frame #22: 0x000000010573e150 UIKit-[UIViewController _setViewAppearState:isAnimating:] + 444
      frame #23: 0x000000010573e9e5 UIKit-[UIViewController __viewWillAppear:] + 147 frame #24: 0x000000010576aa3b UIKit-[UINavigationController _startCustomTransition:] + 1195
      frame #25: 0x00000001057813b4 UIKit-[UINavigationController _startDeferredTransitionIfNeeded:] + 686 frame #26: 0x00000001057826d3 UIKit-[UINavigationController __viewWillLayoutSubviews] + 150
      frame #27: 0x00000001059dd4e2 UIKit-[UILayoutContainerView layoutSubviews] + 231 frame #28: 0x0000000105661a6d UIKit-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1439
      frame #29: 0x000000010c69e61c QuartzCore-[CALayer layoutSublayers] + 159 frame #30: 0x000000010c6a27ad QuartzCoreCA::Layer::layout_if_needed(CA::Transaction*) + 401
      frame #31: 0x000000010c62986c QuartzCoreCA::Context::commit_transaction(CA::Transaction*) + 364 frame #32: 0x000000010c656946 QuartzCoreCA::Transaction::commit() + 500
      frame #33: 0x000000010c657694 QuartzCoreCA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 76 frame #34: 0x0000000108043c07 CoreFoundationCFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION + 23
      frame #35: 0x0000000108043b5e CoreFoundation__CFRunLoopDoObservers + 430 frame #36: 0x0000000108028124 CoreFoundation__CFRunLoopRun + 1572
      frame #37: 0x0000000108027889 CoreFoundationCFRunLoopRunSpecific + 409 frame #38: 0x000000010bf599c6 GraphicsServicesGSEventRunModal + 62
      frame #39: 0x00000001055905d6 UIKitUIApplicationMain + 159 frame #40: 0x0000000104488e7f FBRecycleTestmain(argc=1, argv=0x00007ffeeb7780d0) at main.m:14
      frame #41: 0x0000000108691d81 libdyld.dylib`start + 1

(FB::RetainCycleDetector::Parser::Type *) this = 0x000060c000127b38
this->name:
(std::__1::string) name = ""
Printing description of this->name._r:
(std::__1::__compressed_pair<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >::__rep, std::__1::allocator >) _r = {
std::__1::__libcpp_compressed_pair_imp<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >::__rep, std::__1::allocator, 2> = {
_first = {
= {
__l = (_cap = 0, _size = 0, _data = 0x0000000000000000)
__s = {
= (_size = '\0', __lx = '\0')
_data = {
[0] = '\0'
[1] = '\0'
[2] = '\0'
[3] = '\0'
[4] = '\0'
[5] = '\0'
[6] = '\0'
[7] = '\0'
[8] = '\0'
[9] = '\0'
[10] = '\0'
[11] = '\0'
[12] = '\0'
[13] = '\0'
[14] = '\0'
[15] = '\0'
[16] = '\0'
[17] = '\0'
[18] = '\0'
[19] = '\0'
[20] = '\0'
[21] = '\0'
[22] = '\0'
}
}
__r = {
__words = ([0] = 0, [1] = 0, [2] = 0)
}
}
}
}
}
Printing description of this->typeEncoding:
(std::__1::string) typeEncoding = "`I\x04\x01\0"
Printing description of this->typePath:
(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > > >) typePath = size=0 {}

__block variables have been capture by the block,but 'dispose_helper' error

__block variables have been capture by the block,but 'dispose_helper' error , Demo:

__weak CDItem *item = [CDItem new];
__block NSInteger index = 10;
void (^callblock)(NSString *name) = ^(NSString *name){
item.name = name;
index = 20;
};
callblock(@"jack");
void *block = (__bridge void *)callblock;
NSIndexSet *set = GetBlockStrongLayout(block); // FBBlockStrongLayout中_GetBlockStrongLayout(...)实现

error:
dispose_helper -- Thread 1: EXC_BAD_ACCESS (code=1, address=0x10)

*** -[NSTaggedPointerStringCStringContainer release]: message sent to deallocated instance 0x7fafe61c0370

hi :
i have a demo and imported FBRetainCycleDetector framework, i hook NSObject's init method and then get a instance ,code as follows

    Method oriStartM1 = class_getInstanceMethod([NSObject class], @selector(init));
    Method newStartM1 = class_getInstanceMethod([NSObject class], @selector(initMy));
    method_exchangeImplementations(oriStartM1, newStartM1);
@implementation NSObject (Hook)

- (id)initMy {
    id ss = [self initMy];
    NSString *className = NSStringFromClass([ss class]);
    if (![className hasPrefix:@"FB"]&&![ss isKindOfClass:NSClassFromString(@"MyRetainCycle")] && [[[MyRetainCycle defaulCycle] objects] containsObject:className]) {
        [[[MyRetainCycle defaulCycle] detector] addCandidate:ss];
    }
    return ss;
}

@end

then i have a timer in MyRetainCycle class to check every 2 seconds,code as follows

@implementation MyRetainCycle

+ (MyRetainCycle *)defaulCycle {
    static MyRetainCycle *myRetainCycle = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        myRetainCycle = [[MyRetainCycle alloc] init];
        myRetainCycle.objects = [NSMutableArray array];
        myRetainCycle.detector = [FBRetainCycleDetector new];
        [NSTimer scheduledTimerWithTimeInterval:2 target:myRetainCycle selector:@selector(checkcheckcheck) userInfo:nil repeats:YES];
    });
    return myRetainCycle;
}

- (void)checkcheckcheck {
    NSSet *retainCycles = [_detector findRetainCycles];
    NSLog(@"-----++++------%@", retainCycles);

}

@end

but i always get a crash

*** -[NSTaggedPointerStringCStringContainer retain] called, not supposed to happen
*** -[NSTaggedPointerStringCStringContainer retain] called, not supposed to happen
*** -[NSTaggedPointerStringCStringContainer retain] called, not supposed to happen
*** -[NSTaggedPointerStringCStringContainer retain] called, not supposed to happen
*** -[NSTaggedPointerStringCStringContainer retain] called, not supposed to happen
*** -[NSTaggedPointerStringCStringContainer retain] called, not supposed to happen
*** -[NSTaggedPointerStringCStringContainer retain] called, not supposed to happen
*** -[NSTaggedPointerStringCStringContainer retain] called, not supposed to happen

*** -[NSTaggedPointerStringCStringContainer release]: message sent to deallocated instance 0x7fafe61c0370

and crash thread last stacks are
2016-04-21 7 04 31

can anyone help me? thank you~

crash at NSCAssert

crash at this line (Xcode 9 beta 5, iOS 11 beta 6)
NSCAssert(nameFromBefore, @"There should always be a name from before if we hit a struct");

exception 'NSInternalInconsistencyException'

*** Assertion failure in struct _StructParseResult FB::RetainCycleDetector::Parser::_ParseStructEncodingWithScanner((anonymous namespace)::_StringScanner &)(), /Users/abc/Documents/demo/NewProj/Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/Parser/FBStructEncodingParser.mm:108
2017-11-17 17:38:50.231679+0800 NewProj[13102:533451] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'There should always be a name from before if we hit a struct'
*** First throw call stack:
(
0 CoreFoundation 0x000000010692a1cb __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010628cf41 objc_exception_throw + 48
2 CoreFoundation 0x000000010692f362 +[NSException raise:format:arguments:] + 98
3 Foundation 0x0000000102ed2523 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 165
4 NewProj 0x00000001016788b0 _ZN2FB19RetainCycleDetector6ParserL31_ParseStructEncodingWithScannerERN12_GLOBAL__N_114_StringScannerE + 5152
5 NewProj 0x00000001016772c1 ZN2FB19RetainCycleDetector6Parser27parseStructEncodingWithNameERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESA + 81
6 NewProj 0x000000010166c8b1 _ZL41FBGetReferencesForObjectsInStructEncodingP15FBIvarReferenceNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE + 465
7 NewProj 0x000000010166c540 FBGetClassReferences + 512
8 NewProj 0x000000010166dae8 _ZL29FBGetStrongReferencesForClassP10objc_class + 24
9 NewProj 0x000000010166d970 FBGetObjectStrongReferences + 320
10 NewProj 0x0000000101672801 -[FBObjectiveCObject allRetainedObjects] + 369
11 NewProj 0x00000001016701c7 -[FBNodeEnumerator nextObject] + 103
12 NewProj 0x00000001016740c8 -[FBRetainCycleDetector _findRetainCyclesInObject:stackDepth:] + 472
13 NewProj 0x0000000101673cf5 -[FBRetainCycleDetector findRetainCyclesWithMaxCycleLength:] + 437
14 NewProj 0x000000010165e9db __95-[FBMemoryProfilerViewController _findRetainCyclesForClassesNamed:inGeneration:presentDetails:]_block_invoke + 1083
15 libdispatch.dylib 0x0000000106e9a3f7 _dispatch_call_block_and_release + 12
16 libdispatch.dylib 0x0000000106e9b43c _dispatch_client_callout + 8
17 libdispatch.dylib 0x0000000106ea0352 _dispatch_queue_override_invoke + 1458
18 libdispatch.dylib 0x0000000106ea71f9 _dispatch_root_queue_drain + 772
19 libdispatch.dylib 0x0000000106ea6e97 _dispatch_worker_thread3 + 132
20 libsystem_pthread.dylib 0x000000010735e5a2 _pthread_wqthread + 1299
21 libsystem_pthread.dylib 0x000000010735e07d start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

findRetainCycles can't find retain cycle in UIView`s hierarchy

Let we have next class:
@interface CustomView : UIView
@Property (nonatomic, copy) void(^customBlock)(void);
@EnD
@implementation CustomView
@EnD

Than make retain cycle in app:
CustomView *view1 = [[CustomView alloc] initWithFrame:CGRectZero];
CustomView *view2 = [[CustomView alloc] initWithFrame:CGRectZero];
[view1 addSubview:view2];
view2.customBlock = ^{
view1.customBlock = NULL;
};

Next code will be not find this retain cycle:
NSArray *objects = [[FBAllocationTrackerManager sharedManager] instancesOfClasses:@[[CustomView class]]];
FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
for (id object in objects) {
[detector addCandidate:object];
}
NSSet *retainCycles = [detector findRetainCycles];

Is This support iOS 11 ?

It's crash in iOS 11:

NSCAssert(nameFromBefore, @"There should always be a name from before if we hit a struct");

Why is it necessary to execute _shiftBufferToLowestAddress?

I noticed _shiftBufferToLowestAddress is executed before _shiftToLowestLexicographically。
But I think the function _shiftToLowestLexicographically can alone guarantee the uniqueness of the shift of the array。
So is there any necessity to call _shiftBufferToLowestAddress?

NSGetSizeAndAlignment(): unsupported type encoding spec

Hi guys,

In my mixed Swift/ObjC project, I copy/pasted the instructions under "Example usage" into a ObjC file. At

NSSet *retainCycles = [detector findRetainCycles];

I got an objc_exception

NSGetSizeAndAlignment(): unsupported type encoding spec 'b' at 'b2' in 'b2'

from FBClassStrongLayout.m line 43.

I use FBRetainCycleDetector (0.1.1) via CococaPods (with frameworks enabled)

"Segmentation fault: 11" during a compilation or "The LLDB RPC server has crashed" during a runtime

I have installed FBRetainCycleDetector by cocoapods.
I successfully created FBRetainCycleDetector and added candidates.

When I try to call findRetainCycles by LLDB I get next
"The LLDB RPC server has crashed"
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 com.XXXX-gmbh.XXXX 0x00000001024e0edb _TFC6XXX23XXXX14viewWillAppearfSbT_ + 363 (AnalyticsServiceInterface.swift:137) 1 com.XXXX-gmbh.XXXX 0x00000001024e0f06 _TToFC6XXXX23XXXX14viewWillAppearfSbT_ + 38 2 com.apple.UIKit 0x000000010586a2bd -[UIViewController _setViewAppearState:isAnimating:] + 710 3 com.apple.UIKit 0x000000010586a958 -[UIViewController __viewWillAppear:] + 149 4 com.apple.UIKit 0x00000001058a9c83 -[UINavigationController _startTransition:fromViewController:toViewController:] + 781 5 com.apple.UIKit 0x00000001058aac4d -[UINavigationController _startDeferredTransitionIfNeeded:] + 890 6 com.apple.UIKit 0x00000001058abd0b -[UINavigationController __viewWillLayoutSubviews] + 57 7 com.apple.UIKit 0x0000000105a5a503 -[UILayoutContainerView layoutSubviews] + 248 8 com.apple.UIKit 0x0000000105784980 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 703 9 com.apple.QuartzCore 0x00000001053d4c00 -[CALayer layoutSublayers] + 146 10 com.apple.QuartzCore 0x00000001053c908e CA::Layer::layout_if_needed(CA::Transaction*) + 366 11 com.apple.QuartzCore 0x00000001053c8f0c CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 24 12 com.apple.QuartzCore 0x00000001053bd3c9 CA::Context::commit_transaction(CA::Transaction*) + 277 13 com.apple.QuartzCore 0x00000001053eb086 CA::Transaction::commit() + 486 14 com.apple.QuartzCore 0x00000001053eb7f8 CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 92 15 com.apple.CoreFoundation 0x0000000107d37c37 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 16 com.apple.CoreFoundation 0x0000000107d37ba7 __CFRunLoopDoObservers + 391 17 com.apple.CoreFoundation 0x0000000107d2d7fb __CFRunLoopRun + 1147 18 com.apple.CoreFoundation 0x0000000107d2d0f8 CFRunLoopRunSpecific + 488 19 com.apple.GraphicsServices 0x000000010bd90ad2 GSEventRunModal + 161 20 com.apple.UIKit 0x00000001056c9f09 UIApplicationMain + 171 21 com.xxxx-gmbh.xxxx 0x00000001024851e0 main + 48 (AppDelegate.swift:17) 22 libdyld.dylib 0x00000001094c592d start + 1

When I try add a next code:
let cycles = detector.findRetainCycles()
print(cycles)
I get "Segmentation fault: 11" during compilation.

0 swift 0x000000010aaaa4f7 PrintStackTraceSignalHandler(void*) + 39 1 swift 0x000000010aaa99a6 SignalHandler(int) + 646 2 libsystem_platform.dylib 0x00007fffe361fb3a _sigtramp + 26 3 libsystem_platform.dylib 0x00007fff583a8be8 _sigtramp + 1960349896 4 swift 0x0000000107909c76 swift::irgen::emitArchetypeWitnessTableRef(swift::irgen::IRGenFunction&, swift::CanTypeWrapper<swift::ArchetypeType>, swift::ProtocolDecl*) + 246 5 swift 0x00000001079f9686 swift::irgen::emitWitnessTableRef(swift::irgen::IRGenFunction&, swift::CanType, llvm::Value**, swift::ProtocolConformanceRef) + 102 6 swift 0x00000001079f9da0 void llvm::function_ref<void (swift::irgen::GenericRequirement)>::callback_fn<(anonymous namespace)::EmitPolymorphicArguments::emit(swift::CanTypeWrapper<swift::SILFunctionType>, llvm::ArrayRef<swift::Substitution>, swift::irgen::WitnessMetadata*, swift::irgen::Explosion&)::$_14>(long, swift::irgen::GenericRequirement) + 544 7 swift 0x00000001079f7ce2 void llvm::function_ref<void (swift::irgen::GenericRequirement)>::callback_fn<(anonymous namespace)::PolymorphicConvention::enumerateUnfulfilledRequirements(llvm::function_ref<void (swift::irgen::GenericRequirement)> const&)::$_7>(long, swift::irgen::GenericRequirement) + 162 8 swift 0x00000001079ef32d (anonymous namespace)::PolymorphicConvention::enumerateRequirements(llvm::function_ref<void (swift::irgen::GenericRequirement)> const&) + 253 9 swift 0x00000001079f98bf swift::irgen::emitPolymorphicArguments(swift::irgen::IRGenFunction&, swift::CanTypeWrapper<swift::SILFunctionType>, swift::CanTypeWrapper<swift::SILFunctionType>, llvm::ArrayRef<swift::Substitution>, swift::irgen::WitnessMetadata*, swift::irgen::Explosion&) + 431 10 swift 0x0000000107a5dee5 (anonymous namespace)::IRGenSILFunction::visitFullApplySite(swift::FullApplySite) + 2453 11 swift 0x0000000107a459ca swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 9626 12 swift 0x000000010795d691 swift::irgen::IRGenerator::emitGlobalTopLevel() + 1041 13 swift 0x0000000107a2c45f performIRGeneration(swift::IRGenOptions&, swift::ModuleDecl*, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule> >, llvm::StringRef, llvm::LLVMContext&, swift::SourceFile*, llvm::GlobalVariable**, unsigned int) + 1695 14 swift 0x00000001078ca747 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 51031 15 swift 0x0000000107877d6c main + 9052 16 libdyld.dylib 0x00007fffe3410235 start + 1

Did I do something wrong?

OBJC_ASSOCIATION_COPY should be viewed as a strong reference?

OBJC_ASSOCIATION_COPY and OBJC_ASSOCIATION_COPY_NONATOMIC specifies that the associated object is copied, which means that the object has a strong reference to the associated value (in my understanding).

Is that any special consideration to ignore this reference in the function below? 🤔

static void fb_objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy) {
  {
    std::lock_guard<std::mutex> l(*_associationMutex);
    // Track strong references only
    if (policy == OBJC_ASSOCIATION_RETAIN ||
        policy == OBJC_ASSOCIATION_RETAIN_NONATOMIC) {
      _threadUnsafeSetStrongAssociation(object, key, value);
    } else {
      // We can change the policy, we need to clear out the key
      _threadUnsafeResetAssociationAtKey(object, key);
    }
  }

about private APIs in `FBRetainCycleDetector`

hi, I see the comment before the macro RETAIN_CYCLE_DETECTOR_ENABLED in file FBRetainCycleDetector.h

/**
 Retain Cycle Detector is enabled by default in DEBUG builds, but you can also force it in other builds by
 uncommenting the line below. Beware, Retain Cycle Detector uses some private APIs that shouldn't be compiled in
 production builds.
 */

I want use FBRetainCycleDetector in production environment to find retain cycles, so I want know what Private APIs of FBR use.
thanks a lot!

`FBIvarReference *wrapper = [[FBIvarReference alloc] initWithIvar:ivar];` crashed when ivar is NULL

hi, dudes

I am hitting a situation that when detecting an instance retain cycle references, the
*FBIvarReference wrapper = [[FBIvarReference alloc] initWithIvar:ivar]; in function
*NSArray<id> FBGetClassReferences(Class aCls)
was called, and the ivar was NULL by coincidence, then the program crashes because of EXC_BAD_ACCESS, so I added

if (typeEncoding == NULL) {
    return FBUnknownType;
  }

in front of

if (typeEncoding[0] == '{') {
    return FBStructType;
  }

in method *- (FBType)_convertEncodingToType:(const char )typeEncoding of FBIvarReference class. My problem was resolved then, so I am just curious if this defensive code should be added.

Any useful reply will be appreciated. ^_^

Array argument is not an NSArray

Hey,

When I try to use your library, I run into a Array argument is not an NSArray exception whenever I try to call findRetainCycles.

The issue seems to be coming from here.

I'm running on XCode 3.8.1 targeting iOS 8.0.

Any ideas?

-[NSMutableArray addObjectsFromArray:]: array argument is not an NSArray
-[UncaughtExceptionHandler handleException:] [Line 72] exception: *** -[NSMutableArray addObjectsFromArray:]: array argument is not an NSArray, with info:{
	    UncaughtExceptionHandlerAddressesKey = (
		0   CoreFoundation                      0x000000011076fb0b __exceptionPreprocess + 171
		1   libobjc.A.dylib                     0x0000000116b5c141 objc_exception_throw + 48
		2   CoreFoundation                      0x00000001106ef571 -[NSMutableArray addObjectsFromArray:] + 625
		3   FBRetainCycleDetector               0x0000000110e3186b FBGetObjectStrongReferences + 443
		4   FBRetainCycleDetector               0x0000000110e363d1 -[FBObjectiveCObject allRetainedObjects] + 369
		5   FBRetainCycleDetector               0x0000000110e33db7 -[FBNodeEnumerator nextObject] + 103
		6   FBRetainCycleDetector               0x0000000110e37c37 -[FBRetainCycleDetector _findRetainCyclesInObject:stackDepth:] + 471
		7   FBRetainCycleDetector               0x0000000110e3786f -[FBRetainCycleDetector findRetainCyclesWithMaxCycleLength:] + 447
		8   FBRetainCycleDetector               0x0000000110e376a2 -[FBRetainCycleDetector findRetainCycles] + 50
		9   Whova                               0x000000010e658920 -[AgendaVC dealloc] + 144
		10  UIKit                               0x00000001115d24e4 __destroy_helper_block_.125 + 80
		11  libsystem_blocks.dylib              0x000000011592399d _Block_release + 111
		12  UIKit                               0x00000001116a2e37 -[UIViewAnimationBlockDelegate .cxx_destruct] + 43
		13  libobjc.A.dylib                     0x0000000116b5a9bc _ZL27object_cxxDestructFromClassP11objc_objectP10objc_class + 127
		14  libobjc.A.dylib                     0x0000000116b66d34 objc_destructInstance + 129
		15  libobjc.A.dylib                     0x0000000116b66d66 object_dispose + 22
		16  libobjc.A.dylib                     0x0000000116b70b8e _ZN11objc_object17sidetable_releaseEb + 202
		17  CoreFoundation                      0x00000001106d858d -[__NSDictionaryI dealloc] + 125
		18  libobjc.A.dylib                     0x0000000116b70b8e _ZN11objc_object17sidetable_releaseEb + 202
		19  libobjc.A.dylib                     0x0000000116b712fa _ZN12_GLOBAL__N_119AutoreleasePoolPage3popEPv + 866
		20  CoreFoundation                      0x00000001106beef6 _CFAutoreleasePoolPop + 22
		21  CoreFoundation                      0x00000001106faaec __CFRunLoopRun + 2172
		22  CoreFoundation                      0x00000001106fa016 CFRunLoopRunSpecific + 406
		23  GraphicsServices                    0x000000011881ea24 GSEventRunModal + 62
		24  UIKit                               0x00000001115ea0d4 UIApplicationMain + 159
		25  Whova                               0x000000010e2497d9 main + 137
		26  libdyld.dylib                       0x00000001158db65d start + 1
	);
	}

rcd_fishhook had rename,When will the new version be released

I have a pod dependent on the pod fishhook and FBRetainCycleDetector,but the old version of FBRetainCycleDetector have a file fishhook,and also the fishhook file function-name has a Prefix rac_,it is a reason My project compilation failed,please release a new version to solve it. Thanks!

new version

seems the latest version is v0.1.4 which was 2 years old, why not bump a new version to release(many bugs had been fixed).

MobSF reported use of unsecured function

We have used MobSF client to analyse our app and it has reported the use of following unsecured functions which are used by flex

_strlen/strlen
_memcpy/memcpy

_FBNSCFTimerInfoStruct will crash, can't support block of timer

if (context.info && context.retain) { xxxx }

should modify to

if (context.info && context.retain) { const char *type = object_getClassName((__bridge id)context.info); if (strcmp(type, "__NSMallocBlock__") || strcmp(type, "__NSGlobalBlock__") || strcmp(type, "__NSStackBlock__")) { CFRunLoopTimerCallBack *callBack = (CFRunLoopTimerCallBack *)(context.info); } else { xxxx } }

findRetainCycles() error in swift

I am trying to use FBRetainCycleDetector in swift as following :

var detector: FBRetainCycleDetector = FBRetainCycleDetector()

var retainCycles: Set<[FBObjectCGraphElement]> = detector.findRetainCycles()  

But it gives error at retainCycles saying Type [FBObjectiveCGraphElement] does not confirm to the protocol HashTable
screen shot 2016-06-14 at 6 36 26 pm

I am not sure if this is being working as designed since it should be working with Swift code too ?

PS: I would have loved to post it on stack overflow instead of taking your precious time but I don't see any questions being answered for the related topics such as FBMemoryProfiler/FBAllocationTracker/FBRetainCycleDetector

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.