gpt4 book ai didi

xcode - 如何记录 CFType 对象的分配、保留、释放和解除分配的消息/中断执行?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:47:02 24 4
gpt4 key购买 nike

我希望能够在每次特定的 CFType 时记录消息(最好是中断调试器)对象(对于我目前的目的,一个 CGPDFDocument )被分配、保留、释放或释放。

因为没有 Create...() CGPDFDocument 的方法这需要 CFAllocatorRef ,我正在尝试像这样临时更改默认分配器:

void MyPDFDocumentCreate()
{
// ...

CFAllocatorRef defaultAllocator = CFAllocatorGetDefault();
CFAllocatorSetDefault(MyLogAllocator());

CGPDFDocumentRef documentRef = CGPDFDocumentCreateWithProvider(provider);

CFAllocatorSetDefault(defaultAllocator);

// ...
}

哪里MyLogAllocator()定义如下:

static void *(*DefaultAllocate)(CFIndex size, CFOptionFlags hint, void *info);
static const void *(*DefaultRetain)(const void *info);
static void (*DefaultRelease)(const void *info);

void *LogAllocate(CFIndex size, CFOptionFlags hint, void *info)
{
fprintf(stderr, "LogAllocate %p", info);
if (DefaultAllocate)
return DefaultAllocate(size, hint, info);
else
return NULL;
}

const void *LogRetain(const void *info)
{
fprintf(stderr, "LogRetain");
if (DefaultRetain)
return DefaultRetain(info);
else
return info;
}

void LogRelease(const void *info)
{
fprintf(stderr, "LogRelease");
if (DefaultRelease)
DefaultRelease(info);
}

static CFAllocatorRef MyLogAllocator()
{
static CFAllocatorRef theLogAllocator = NULL;

if (!theLogAllocator)
{
CFAllocatorContext context;
CFAllocatorRef defaultAllocator = CFAllocatorGetDefault();
CFAllocatorGetContext(defaultAllocator, &context);

DefaultAllocate = context.allocate;
DefaultRetain = context.retain;
DefaultRelease = context.release;

context.allocate = LogAllocate;
context.retain = LogRetain;
context.release = LogRelease;

theLogAllocator = CFAllocatorCreate(kCFAllocatorUseContext, &context);
}

return theLogAllocator;
}

但是,似乎默认分配器(据我所知为 kCFAllocatorSystemDefault)对于 context.retain 和 context.release 为 NULL,因此我没有任何原始实现可以调用。这可能就是为什么当我尝试上面的代码时,我得到以下堆栈跟踪:

#0  0x357ded12 in CFRetain ()
#1 0x357dcb68 in _CFRuntimeCreateInstance ()
#2 0x303fe35e in CGTypeCreateInstanceWithAllocator ()
#3 0x303fe34c in CGTypeCreateInstance ()
#4 0x304b32f4 in CGPDFDocumentCreateWithProvider ()
#5 0x000293f4 in MyPDFDocumentCreate ([...]) at [...]

XCode 实际上并没有告诉我它停止的原因,但如果我尝试继续,我会得到:

(gdb) continue
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x357ded12 in CFRetain ()
(gdb) continue
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x357ded12 in CFRetain ()
(gdb)

无论我继续多少次,我都会得到相同的 SIGTRAP。我不知道如何解释它;我设置的唯一断点是 objc_exception_throw 上的一个象征性断点.

需要注意的一件事是 LogRetain()LogAllocate()每个都从 CFAllocatorCreate() 成功调用一次(按顺序) :

#0  LogRetain (info=0x1a8000) at [...]
#1 0x358086f2 in CFAllocatorCreate ()
#2 0x00028d58 in MyLogAllocator () at [...]
#3 0x000293e0 in MyPDFDocumentCreate ([...]) at [...]

#0 LogAllocate (size=104, hint=0, info=0x1a8000) at [...]
#1 0x3580882e in CFAllocatorCreate ()
#2 0x00028d58 in MyLogAllocator () at [...]
#3 0x000293e0 in MyPDFDocumentCreate ([...]) at [...]

然后 LogAllocate()CFAllocatorAllocate()再次成功:

#0  LogAllocate (size=64, hint=1024, info=0x1a8000) at [...] 
#1 0x357dcc06 in CFAllocatorAllocate ()
#2 0x357dcb04 in _CFRuntimeCreateInstance ()
#3 0x303fe35e in CGTypeCreateInstanceWithAllocator ()
#4 0x303fe34c in CGTypeCreateInstance ()
#5 0x304b32f4 in CGPDFDocumentCreateWithProvider ()
#6 0x000293f4 in MyPDFDocumentCreate ([...]) at [...]

_CFRuntimeCreateInstance() 之前在 #2 调用有问题的 CFRetain()上面有详细说明。

有人能帮我理解这里发生了什么吗(特别是默认分配器如何处理保留和释放,以及为什么我得到 SIGTRAP);如何修复它;以及是否有更好的方法来完成我想做的事情?

(我想我也许能够弄清楚如何使用 DTrace 来探测 CFRetain()CFRelease() ,由 CFTypeID 过滤为 CGPDFDocument ,但我不知道要探测什么以进行释放(跟踪分配并不重要,因为我知道它是在 CGPDFDocumentCreateWithProvider() 内完成的。此外,我更希望能够在保留/释放/解除分配时中断调试器,我认为使用 DTrace 不可能做到这一点。 )

更新:现在阅读 source code对于 CFRelease我意识到我误解了 context.retain 的目的和 context.release -- 它们用于保留和释放 context.info .所以上面描述的整个方法是行不通的。然而,也许 DTrace/Instruments 向导仍然可以施展魔法?!

最佳答案

这是一个非常有趣的问题。由于您已经深入研究过滤 DTrace,并且正在深入研究 CFRelease 源代码,因此您可以查看使用 gdb 断点条件来选择何时中断。要确定是否会发生释放,只需使用 CFGetRetainCount()

就是说,我猜您正在急于追踪一些过度发布的崩溃,对吗?要看的东西可能比逆向工程更有用CFRelease():

  • CFZombie
  • Instruments 的 Allocations 工具提供对象何时被保留和释放、分配和销毁的完整堆栈。打开“记录引用计数”选项。

关于xcode - 如何记录 CFType 对象的分配、保留、释放和解除分配的消息/中断执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5098966/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com