为什么 __stack_chk_fail 在来自 ipa 的 运行 时发生,而不是在 Xcode 中的设备上 运行 时发生?

Why does __stack_chk_fail happen when running from ipa, but not when running on device in Xcode?

这是具体的堆栈跟踪,请参阅下面的代码...

Thread 8 Crashed:
0   libsystem_kernel.dylib          0x00000001969bb270 __pthread_kill + 8
1   libsystem_pthread.dylib         0x0000000196a5916c pthread_kill + 108
2   libsystem_c.dylib               0x0000000196932b94 __abort + 112
3   libsystem_c.dylib               0x00000001969333f8 __stack_chk_fail + 208

只有在我为企业部署导出 ipa 并尝试在我的设备上 运行 之后才会出现这种情况。同样的设备,在 Xcode 中调试时 运行 就可以了。有什么想法吗?我在做什么破坏了堆栈?

// MACROS USED
#define BUFFER_SIZE_MAX 20480 // 20KB max payload for URL requests
#define BUFFER_SIZE_READ 4096 // 4KB
#define BUFFER_SIZE 4100 // 4KB w padding
#define NUL '[=15=]'
... relavent code ...

char readBuffer[BUFFER_SIZE] = {};
long bytesRead = 0;
char *buff = NULL;
while (((bytesRead = read(sck, readBuffer, BUFFER_SIZE_READ)) > 0)) {
    if (!stop || *stop) {  // volatile bool* passed to method
        break;
    }
    if (bytesRead > 0) {
        readBuffer[bytesRead] = NUL; // add NUL terminator
    }
    long len = bytesRead;
    if (buff) {
        len += strlen(buff);
        buff = (char *)realloc(buff, len * sizeof(char));
    } else {
        buff = (char *)malloc(len * sizeof(char));
        buff[0] = NUL;
    }
    strcat(buff, readBuffer);
    if (strlen(buff) >= BUFFER_SIZE_MAX) {
        // payload shouldn't be bigger than 20K in most use-cases
        // adjust BUFFER_SIZE_MAX as needed
        break;

    }
}
if (buff) {
    response = strdup(buff);
    free(buff);
}
LOGV("\n\n<<<<<============\nHTTP payload:\n<<<<<============>>>>>>");
LOGV("\n\nREQUEST:\n----------->\n%s", request);
LOGV("\n\nRESPONSE:\n----------->\n%s\n\n", response);
close(sck);
return response; /// must call free

这里有一些问题,其中任何一个都可能导致您的问题:

1) readBuffer 的大小为 4100 字节。 但是当你 "readBuffer[bytesRead] = NUL;" 你 可以 写入 readBuffer[4100] 即超过缓冲区的末尾。 char readBuffer[BUFFER_SIZE] 应该是 char readBuffer[BUFFER_SIZE+1].

2) buff = (char *)malloc(len * sizeof(char)); 您分配了收到的数据量,但不允许在调用 strcat() 时添加空终止符。你应该分配 (len + 1).

3) buff = (char *)realloc(buff, len * sizeof(char)); 您再次分配时不考虑空终止符。 应该是 buff = (char *)realloc(buff, (len+1) * sizeof(char));

当您写入不属于您的内存时,行为就会变得不确定。所以有些时候它可能是个问题,其他时候你可能会侥幸逃脱。这取决于您要覆盖的内存中存在的内容。所以你总是在这里做坏事,但只是有时看到它的后果。