- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下代码(RAD Studio XE2,Windows 7 x64):
program letters;
{$APPTYPE CONSOLE}
{$DEFINE BOO}
const
ENGLISH_ALPHABET = 'abcdefghijklmnopqrstuvwxyz';
begin
{$IFDEF BOO}
writeln;
{$ENDIF}
write(ENGLISH_ALPHABET[1]:3);
readln;
end.
当{$DEFINE BOO}
指令关闭时,我有以下(预期)输出(为了便于阅读,空格被替换为点):
..a
当指令打开时,我有以下(意外的)输出:
// empty line here
?..a
与预期不同
// empty line here
..a
当我将 const ENGLISH_ALPHABET
更改为 const ENGLISH_ALPHABET: AnsiString
时,打印的预期输出不带疑问字符。当 :3
格式被删除或更改为 :1
时,没有问号。当输出重定向到文件(通过 AssignFile(Output, 'boo.log')
或从命令行)时,不再出现问号。
此行为的正确解释是什么?
最佳答案
这是 RTL 中的一个相当奇怪的错误。对 write
的调用解析为对 _WriteWChar
的调用。这个函数的实现是这样的:
function _WriteWChar(var t: TTextRec; c: WideChar; width: Integer): Pointer;
begin
if width <= 1 then
result := _Write0WChar(t, c)
else
begin
if t.UTF16Buffer[0] <> #0 then
begin
_Write0WChar(t, '?');
t.UTF16Buffer[0] := #0;
end;
_WriteSpaces(t, width - 1);
Result := _Write0WChar(t, c);
end;
end;
您看到的 ?
是由上面的代码发出的。
那么,为什么会发生这种情况呢?我可以构建的最简单的 SSCCE 是这样的:
{$APPTYPE CONSOLE}
const
ENGLISH_ALPHABET = 'abcdefghijklmnopqrstuvwxyz';
begin
writeln;
write(ENGLISH_ALPHABET[1]:3);
end.
因此,您的第一次调用 writeln
解析为:
function _WriteLn(var t: TTextRec): Pointer;
begin
if (t.Flags and tfCRLF) <> 0 then
_Write0Char(t, _AnsiChr(cCR));
Result := _Write0Char(t, _AnsiChr(cLF));
_Flush(t);
end;
在这里,您将单个字符,cLF
,ASCII 字符 10,换行符推送到输出文本记录上。这会导致 t.MBCSBuffer
被输入 cLF
字符。该字符保留在缓冲区中,这很好,因为 System._Write0Char.WriteUnicodeFromMBCSBuffer 会执行以下操作:
t.MBCSLength := 0;
t.MBCSBufPos := 0;
但是当_WriteWChar
执行时,它会不加区别地查找t.UTF16Buffer
。在 TTextRec
中声明如下:
type
TTextRec = packed record
....
MBCSLength: ShortInt;
MBCSBufPos: Byte;
case Integer of
0: (MBCSBuffer: array[0..5] of _AnsiChr);
1: (UTF16Buffer: array[0..2] of WideChar);
end;
因此,MBCSBuffer
和 UTF16Buffer
共享相同的存储。
该错误是 _WriteWChar
在未首先检查缓冲区长度的情况下不应查看 t.UTF16Buffer
的内容。由于 TTextRec
没有 UTF16Length
,因此如何实现并不是很明显。相反,如果 t.UTF16Buffer
包含有意义的内容,则约定其长度由 -t.MBCSLength
给出!
所以_WriteWChar
也许应该是:
function _WriteWChar(var t: TTextRec; c: WideChar; width: Integer): Pointer;
begin
if width <= 1 then
result := _Write0WChar(t, c)
else
begin
if (t.MBCSLength < 0) and (t.UTF16Buffer[0] <> #0) then
begin
_Write0WChar(t, '?');
t.UTF16Buffer[0] := #0;
end;
_WriteSpaces(t, width - 1);
Result := _Write0WChar(t, c);
end;
end;
这是一个相当卑鄙的黑客,修复了_WriteWChar
。请注意,我无法获取 System._WriteSpaces 的地址来调用它。如果你迫切想解决这个问题,这是可以做的。
{$APPTYPE CONSOLE}
uses
Windows;
procedure PatchCode(Address: Pointer; const NewCode; Size: Integer);
var
OldProtect: DWORD;
begin
if VirtualProtect(Address, Size, PAGE_EXECUTE_READWRITE, OldProtect) then
begin
Move(NewCode, Address^, Size);
FlushInstructionCache(GetCurrentProcess, Address, Size);
VirtualProtect(Address, Size, OldProtect, @OldProtect);
end;
end;
type
PInstruction = ^TInstruction;
TInstruction = packed record
Opcode: Byte;
Offset: Integer;
end;
procedure RedirectProcedure(OldAddress, NewAddress: Pointer);
var
NewCode: TInstruction;
begin
NewCode.Opcode := $E9;//jump relative
NewCode.Offset := NativeInt(NewAddress)-NativeInt(OldAddress)-SizeOf(NewCode);
PatchCode(OldAddress, NewCode, SizeOf(NewCode));
end;
var
_Write0WChar: function(var t: TTextRec; c: WideChar): Pointer;
function _Write0WCharAddress: Pointer;
asm
MOV EAX, offset System.@Write0WChar
end;
function _WriteWCharAddress: Pointer;
asm
MOV EAX, offset System.@WriteWChar
end;
function _WriteWChar(var t: TTextRec; c: WideChar; width: Integer): Pointer;
var
i: Integer;
begin
if width <= 1 then
result := _Write0WChar(t, c)
else
begin
if (t.MBCSLength < 0) and (t.UTF16Buffer[0] <> #0) then
begin
_Write0WChar(t, '?');
t.UTF16Buffer[0] := #0;
end;
for i := 1 to width - 1 do
_Write0WChar(t, ' ');
Result := _Write0WChar(t, c);
end;
end;
const
ENGLISH_ALPHABET = 'abcdefghijklmnopqrstuvwxyz';
begin
@_Write0WChar := _Write0WCharAddress;
RedirectProcedure(_WriteWCharAddress, @_WriteWChar);
writeln;
write(ENGLISH_ALPHABET[1]:3);
end.
我提交了QC#123157 .
关于delphi - writeln (“:width” 说明符的明显副作用会导致输出中出现问号),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41488136/
这2个有什么区别?一个使用 SideEffect,另一个不使用。 “每次成功重组都会调用 SideEffect”,但如果没有 SideEffect,它也会在每次重组时运行。 @Composable f
我在 DOM 元素引用方面遇到了一些问题,我想我已经追踪到它与更新 innerHTML 有关。 在这个例子中,在第一次警告时,两个变量引用同一个元素,正如预期的那样。奇怪的是,在更新父元素(body)
如果有人问过这个问题,请原谅我,但我似乎找不到它。 我正在尝试创建一个数组并反转它(不使用反转)这段代码完美运行: function reverseArrayInPlace(array) { fo
如果 reflector 是正确的(我倾向于相信它是正确的),这就是 Any() 的实现: public static bool Any(this IEnumerable source) {
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
是否可以用 LINQ 中的 lambda 表达式替换 foreach 循环 (.Select))? List l = {1, 2, 3, 4, 5}; foreach (int i in l)
我在一本书上读到以下说法: n = ((i++) > (j)?(i++):(j)); 书上说假设i>j,n有一个意想不到的值,i增加了两次。 我不明白为什么n在这句话之后有一个期望值。 我读了很多关于
我对更改 LD_LIBRARY_PATH 有奇怪的副作用。 当我附加一个包含库的路径时,例如: LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/my_path/lib 然后,一切都
有人能告诉我下面一行中“副作用”的含义吗? If you're calling an EL function that doesn't return anything, then you're cal
是否有为包含副作用的 Java/JVM 语言方法编写 javadoc 的标准或最佳实践? 我定义了一个 void 方法,它修改了方法参数之一,但不知道如何记录实际返回值(因为没有实际返回)。 /**
我正在学习副作用和纯函数。我知道纯函数没有副作用,对于相同的参数,它们的返回值是相同的。我想知道 C 函数 strcmp() 是否是纯函数。我相信它是纯粹的,因为给定相同的两个字符串作为参数,结果将始
我正在尝试创建佛罗里达州的点密度图。虽然我知道 Highmaps 不支持带有 map 点的颜色轴。我扩展了它并且它有效,但它带来了副作用。当我单击图例中的某一类别时,不会发生隐藏。例如,如果我单击“>
我在 CS50 中研究 PSET 4,似乎遇到了 sprintf 更改不相关变量的问题。我只给出了没有揭示我的解决方案的代码...... #include #include #include t
我已经实现了这样的 UnaryOperation struct Converter { Converter( std::size_t value ): value_( valu
使用点符号调用自定义 getter 是否有副作用? 我一直在通过点符号在 Objective-C 中使用合成的 getter,即 tree.fruitnumber 返回树中果实的数量。我必须自定义 s
我无法理解页面 https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/void 中的这一段: This ope
我有一个在 IIS7 下运行的 Web 应用程序。我将全局变量存储在一个带有静态变量的类中。该类称为 SessionVariables 并且在其中例如我有以下内容: public class Sess
运行命令时 ng-packagr -p ng-package.json 我得到以下输出 Building Angular library - - - skipped 8 lines - - - Sid
我想模拟一个 OverflowError 因为我想在引发异常之后测试变量的值。但是,我不知道如何使用我正在使用的库复制 OverflowError。我在此特定测试中使用的库是 pysolar.sola
当我尝试在可变 Map 中插入一个元素时,我希望这个元素插入到我的 Map 而不是返回 Map(如 PF,不可变对象(immutable对象) ecc ...)出于这个原因,我使用了可变集合,但在我的
我是一名优秀的程序员,十分优秀!