我最近撕掉了我的头发调试这段代码(稍为修改以简化演示):
char *packedData;
unsigned char* indexBegin, *indexEnd;
int block, row;
// +------ bad!
// v
int cRow = std::upper_bound( indexBegin, indexEnd, row&255 ) - indexBegin - 1;
char value = *(packedData + (block + cRow) * bytesPerRow);
Run Code Online (Sandbox Code Playgroud)
当然,std::upper_bound在64位环境中将两个指针的差异(减去搜索到的数组的开头的结果)分配给int而不是ptrdiff_t是错误的,但是产生的特殊不良行为是非常意外的.当[indexBegin,indexEnd]的数组大小超过2GB时,我希望这会失败,所以差异溢出了一个int; 但实际发生的事情是当indexBegin和indexEnd在2 ^ 31的两侧有值时(即indexBegin = 0x7fffffe0,indexEnd = 0x80000010)崩溃.进一步的调查揭示了以下x86-64汇编代码(由MSVC++ 2005生成,带有优化):
; (inlined code of std::upper_bound, which leaves indexBegin in rbx,
; the result of upper_bound in r9, block at *(r12+0x28), and data at
; *(r12+0x40), immediately precedes this point)
movsxd rcx, r9d …Run Code Online (Sandbox Code Playgroud) 在哪里可以找到 Emacs Lisp 语法的正式规范(以 EBNF 或其他标准符号表示——“读取”函数的源代码不算在内!)?
我什至对 .y 文件感到满意;不幸的是,emacs 自己的解析器不使用 yacc。