我正在创建一个执行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
答案 0 :(得分:1)
sprintf(buffer, "%s%c", buffer, fgetc(fp));
这是未定义的行为,因为您正在使用缓冲区两次。任何事都可能出错,幸运的是,确实如此。我说“幸运的你”,因为运气不好,只会在客户手中出错。
我没有注意; user3125367发现的问题差十倍。
答案 1 :(得分: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