1

当我从 Xcode 中启动它时,我的 (Cocoa)-App 运行得非常好。但是,当我存档/发布它时,该版本会崩溃。弹出的错误报告器说:

[...]    
Crashed Thread:  0  Dispatch queue: com.apple.main-thread

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000

Application Specific Information:
[9082] stack overflow

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x00007fff944a7212 __pthread_kill + 10
1   libsystem_c.dylib               0x00007fff9290caf4 pthread_kill + 90
2   libsystem_c.dylib               0x00007fff92950e9e __abort + 159
3   libsystem_c.dylib               0x00007fff92951d17 __stack_chk_fail + 195
[...] 

虽然它也给了我执行停止的代码行,但这确实对我没有帮助,因为在调试模式下执行完全相同的代码路径(但成功)。

所以我想知道:实际上可能是版本和调试版本的堆栈大小不同?Mac(64 位/Mountain Lion)上的堆栈到底有多大?我不知道在堆栈上放了很多数据......

如果堆栈上有太多数据,我需要避免哪些模式来减少堆栈负载?

[更新]

好的,我通过添加-fno-stack-protector标志运行了我的应用程序。(顺便说一句:我正在使用 LLVM 进行编译)

在此之前,我逐行浏览了崩溃的代码,发现了以下我不明白的行为:方法foo(x)调用bacon(x). x是 8 并且从foobacon没有修改。然而,当我踏入时bacon(x)x突然是 4295939448(每次)。如果我设置-fno-stack-protector的值是正确的。

在我天真的眼里,这看起来好像堆栈保护器在堆栈中的某个位置设置了魔法值 4295939448 并使其只读。虽然我的函数将它们的参数放在堆栈上,但有时参数x恰好放在那个魔术地址上,因此无法写入(后续参数似乎被正确写入)。在我的例子x中是一个缓冲区长度参数,它自然会导致缓冲区溢出和崩溃。

有人对堆栈保护器有更深入的了解吗?为什么会这样?在什么情况下禁用堆栈保护器是安全和合法的,在什么情况下是危险的?

[更新2:原始代码]

此方法调用Decrypt下面的另一个。此时的 stIVLen 为 8

BOOL CEracomSE::Decrypt(
PBYTE pMsg, size_t stLen,
const CSK* pKey /* = NULL */,
PBYTE pIV /* = NULL */, size_t stIVLen /* = 0 */,
FBM fbm /* = FBM_CBC */,
PADDING padding /* = NO_PADDING */
)
{
    //stIVLen == 8
    return Decrypt( (uint64_t)0, pMsg, stLen, pKey, pIV, stIVLen, fbm, padding ); 
}

调用时DecryptstIVLen是4295939448,其他参数还是正确的

BOOL CEracomSE::Decrypt(
    uint64_t qwOffset, 
    PBYTE pMsg, size_t stLen,
    const CSK* pKey /* = NULL */,
    PBYTE pIV /* = NULL */, size_t stIVLen /* = 0 */,
    FBM fbm /* = FBM_CBC */,
    PADDING padding /* = NO_PADDING */
    )
{
    //stIVLen now is 4295939448
    BYTE a_iv[16] = {0};
    size_t a_iv_len;
    BYTE a_key[32] = {0};
    size_t a_key_len = 0;
    size_t nBytes;
    size_t nDataOffset;
    size_t nRemainingData = stLen;
    bool ret;
    //[...]
}
4

1 回答 1

1

我最近在我的应用程序中遇到了这种情况。我知道这是一个旧线程,但无论如何都会做出回应,目的是让其他人可以从调查结果中受益。

通过-fno-stack-protector确实解决了问题中建议的问题。然而,深入挖掘我们发现,将所有出现的文字数组声明更改为更长的声明确实解决了问题,而无需传递编译器标志。

所以改变所有出现的

@[@(1), @(2)]

[NSArray arrayWithObjects:@(1), @(2), nil]

可能仅适用于我们的应用程序,但希望它也能帮助其他人。

于 2014-09-05T08:22:33.387 回答