【问题标题】:Objective C stringWithCString "Method cache corrupted"Objective C stringWithCString“方法缓存损坏”
【发布时间】:2014-11-22 23:00:55
【问题描述】:

我正在创建一个执行 shell 命令的方法。它看起来像这样:

NSString *cShellStr(NSString *command, int maxBufferSize) {
    if (maxBufferSize<1) {
        maxBufferSize = INT_MAX;
    }
    NSString *newCommand = [NSString stringWithFormat:@"%@ 2>&1", command];
    const char *cStrCommand = [newCommand cStringUsingEncoding:NSUTF8StringEncoding];
    FILE *fp;
    fp = popen(cStrCommand, "r");
    if (fp == NULL) {
        NSLog(@"Failed to open process");
        return nil;
    }
    char *buffer = NULL;
    buffer = (char*)malloc(4);
    if (buffer == NULL) {
        NSLog(@"Failed to allocate memory");
        return nil;
    }
    while (!feof(fp)) {
        buffer = realloc(buffer, sizeof(buffer)+1);
        sprintf(buffer, "%s%c", buffer, fgetc(fp));
    }
    NSString *ret = [NSString stringWithCString:buffer encoding:NSASCIIStringEncoding];
    fclose(fp);
    free(buffer);
    return ret;
}

但是,它通常(奇怪的是并非总是)在[NSString stringWithCString:buffer encoding:NSASCIIStringEncoding] 收到此错误:

objc[33674]: Method cache corrupted. This may be a message to an invalid object, or a memory error somewhere else.
objc[33674]: receiver 0x7fff7d62aec0, SEL 0x7fff99ac69f5, isa 0x7fff7d62aee8, cache 0x7fff7d62aef8, buckets 0x100200780, mask 0x3, occupied 0x2, wrap bucket 0x100200780
objc[33674]: receiver 0 bytes, buckets 64 bytes
objc[33674]: selector 'class'
objc[33674]: isa 'NSString'
objc[33674]: Method cache corrupted.
objc[33674]: Method cache corrupted. This may be a message to an invalid object, or a memory error somewhere else.
objc[33674]: receiver 0x7fff7d62aec0, SEL 0x7fff99aea2d4, isa 0x7fff7d62aee8, cache 0x7fff7d62aef8, buckets 0x100200780, mask 0x3, occupied 0x2, wrap bucket 0x100200780
objc[33674]: receiver 0 bytes, buckets 64 bytes
objc[33674]: selector 'stringWithCString:encoding:'
objc[33674]: isa 'NSString'
objc[33674]: Method cache corrupted.

我已经使用 lldb 逐步检查并确认没有其他错误,并且buffer 包含我所期望的文本。我是否错误地使用了stringWithCString

额外信息: Xcode 版本:

笔记本电脑信息:

Clang 版本:

Apple LLVM version 
6.0 (clang-600.0.51) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix

【问题讨论】:

  • 可能不是实际问题,但 sizeof(buffer)+1 是 /constant/。
  • 是的,任何时候你做sizeofchar* 都肯定是一个错误。在这种情况下,它可能会奏效,但如果您将 buffer 变大,则不会。

标签: objective-c c xcode macos nsstring


【解决方案1】:
while (!feof(fp)) {
    buffer = realloc(buffer, sizeof(buffer)+1);
    sprintf(buffer, "%s%c", buffer, fgetc(fp));
}

这个循环应该重写为:

size_t len = 0, cap = 4;
buffer = malloc(cap); // TODO check NULL
int c;
while (EOF != (c = fgetc(fp))) {
    if (len >= cap) {
        cap += cap;
        buffer = realloc(buffer, cap); // TODO check NULL
    }
    buffer[len++] = c;
}
// check feof/ferror

【讨论】:

    【解决方案2】:
            sprintf(buffer, "%s%c", buffer, fgetc(fp));
    

    这是未定义的行为,因为您使用了两次缓冲区。任何事情都可能出错,幸运的是,它确实如此。我说“你很幸运”,因为如果运气不好,它只会在客户手中出错。

    我没注意; user3125367 发现的问题要严重十倍。

    【讨论】:

    • 这很有用,但不是问题。 user3125367 发现的东西真的把事情搞砸了。不过,我也应该解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 2011-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多