我正在尝试使用以下格式字符串,但这会导致EXC_BAD_ACCESS
尝试从0xC
处objc_msgSend
处读取。 Clang告诉我格式字符串是有效的(除了它有未使用的参数)。这是一个SSCCE:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool
{
NSString* segment = nil;
NSString* base = @"ebp";
char sign = '+';
long long displacement = 12;
long long absDisplacement = llabs(displacement);
NSString* offset = nil;
NSString* nsSize = @"dword";
NSString* r = [NSString stringWithFormat:@"%7$@ ptr [%2$@ %3$c %5$lli]", segment, base, sign, displacement, absDisplacement, offset, nsSize];
NSLog(@"%@", r);
}
return 0;
}
我不使用格式字符串的所有参数,因为要从16种可能性中选择特定格式,并且所有格式字符串中都不使用某些参数(此特定格式字符串忽略参数1,4和6)。类型如下:
NSString*
NSString*
char
long long
long long
NSString*
NSString*
据我所知,我所有的格式说明符都尊重这一点。没有打印对象参数为nil,即使这是stringWithFormat:
支持的方案。
那么我做错了什么?
编辑更改displacement
的值会更改错误的读取地址,但我看不清楚原因。格式字符串对我来说仍然是正确的...我无法弄清楚模式:12次崩溃,12次崩溃,0次爆炸时13次崩溃,0次爆炸造成14次崩溃,0次爆炸造成15次崩溃,16次崩溃造成16次崩溃,导致程序失败退出状态为零而不通过NSLog
。
答案 0 :(得分:4)
答案是在手册页(强调我的):
可选字段,由十进制数字字符串后跟a组成 $,指定要访问的下一个参数。如果不是这个字段 提供,访问的最后一个参数后面的参数将是 用过的。参数从1开始编号。如果未访问 格式字符串中的参数散布在那些参数中 访问结果将是不确定的。
编辑:这是剥离未使用参数的工作版本:
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
@autoreleasepool {
NSString* segment = nil;
NSString* base = @"ebp";
char sign = '+';
long long displacement = 12;
long long absDisplacement = llabs(displacement);
NSString* offset = nil;
NSString* nsSize = @"dword";
NSString* r = [NSString stringWithFormat:@"%4$@ ptr [%1$@ %2$c %3$lli]", base, sign, absDisplacement, nsSize];
NSLog(@"%@", r);
}
}
答案 1 :(得分:1)
您不能在格式字符串中省略某些参数。这是因为C varargs的工作方式 - 参数列表基本上只是一个不加选择的字节流。为了读取参数5,函数需要知道参数1-4的类型,以确定参数5在列表中的位置。