退出 if 语句时内存中的指针已更改


#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
const char* dog = "german shepard";
NSFileManager* fileManager = [NSFileManager defaultManager];
NSString *doglistPath = @"/Users/doglover/doglist.plist";
const char* doglistPath_cString = [doglistPath UTF8String];
const char** doglist;
if ([fileManager fileExistsAtPath:doglistPath]) {
NSArray *doglistPlist = [NSArray arrayWithContentsOfFile:doglistPath];
NSUInteger doglistPlistCount = [doglistPlist count];
const char* doglist2[blacklistPlistCount];
memset(doglist2, 0, sizeof doglist2);
for (int index = 0; index < doglistPlistCount; index++) {
const char *doglistName = [doglistPlist[index][@"type"] UTF8String];
doglist2[index] = doglistName;
}
doglist = doglist2;
}
while(true) {
NSLog(@"%s", *doglist);
doglist++;
}
return 0;
}

列表中有 20 个项目。

每当我运行此代码时,它只打印 4 个项目并给出线程 1:EXC_BAD_ACCESS 错误。

当我检查内存时,当运行时离开 if 语句时,狗列表内存中的指针从 :

B1 78 10 03 01 00 00 00
51 7B 10 03 01 00 00 00
01 7D 10 03 01 00 00 00
A1 7E 10 03 01 00 00 00
91 80 10 03 01 00 00 00
F8 74 10 03 01 00 00 00
11 83 10 03 01 00 00 00
C1 84 10 03 01 00 00 00

B1 78 10 03 01 00 00 00
51 7B 10 03 01 00 00 00
01 7D 10 03 01 00 00 00
A1 7E 10 03 01 00 00 00
40 00 00 00 00 00 00 00
90 ED BF EF FE 7F 00 00
0E 00 B6 D1 69 DA B9 2C
00 00 00 00 00 00 00 00

在更改的内存中,前四个指针确实包含项目,但在0x40时发生错误。

为什么退出 if 语句后内存发生了变化?

一些注意事项:

  1. +arrayWithContentsOfFile已弃用。你不应该使用它。您是否可以控制doglist.plist文件?如果是这样,我建议使用其他编码机制(例如 JSON(存储它。

  2. 在哪里申报blacklistPlistCount?它不在您发布的代码中,这会阻止代码编译。

  3. 您正在使用返回指向缓冲区的指针的-[NSString UTF8String]。但是,不能保证此缓冲区在字符串的生存期之后存在。根据文档:

此 C 字符串是指向字符串对象内部结构的指针,该结构的生存期可能比字符串对象短,并且肯定不会有更长的生存期。因此,如果需要将 C 字符串存储在使用此属性的内存上下文之外,则应复制该字符串。

  1. 为什么要使用低级C指针在C数据结构和Objective-C类型(如NSArrayNSString(之间来回转换?我将使用NSMutableArray进行doglist2,而不是使用 C 数组。除非你正在执行某些专门的任务,否则Objective-C代码中的原始C指针可能是一种代码异味。

无论如何,第 3 点是崩溃的最可能原因,因为当您到达代码中的while循环时,缓冲区早已消失。

最新更新