如果 C 编译器无法证明缺少 UB,为什么要禁止优化?

2024-03-21

如果 C 程序有未定义的行为,任何事情都可能发生。因此编译器可能会假设任何给定的程序不包含 UB。因此,假设我们的程序包含以下内容:

x += 5;
/* Do something else without x in the meantime. */ 
x += 7;

当然,这可以优化为

/* Do something without x. */
x += 12;

或类似的其他方式。

如果 x 有类型unsigned int那么上面的程序中就不存在UB的可能。另一方面,如果 x 具有类型signed int那么就有可能溢出,从而产生 UB。由于编译器可能会假设我们的程序不包含UB,因此我们可以进行与上面相同的优化。事实上,在这种情况下,编译器甚至可以假设x - 12 <= MAX_INT.

然而,这似乎与 Jens Gustedt 的著名理论相矛盾。“现代C” https://www.manning.com/books/modern-c(第 42 页):

但这样的优化也可以被禁止,因为编译器无法证明某个操作不会强制程序终止。在我们的示例中,很大程度上取决于 x 的类型。如果 x 的当前值可能接近类型的上限,则看似无辜的操作 x += 7 可能会产生溢出。此类溢出根据类型的不同而有不同的处理方式。正如我们所看到的,无符号类型的溢出不是问题,并且压缩操作的结果将始终与两个单独的结果一致。对于其他类型,例如有符号整数类型(signed)和浮点类型(double),溢出可能会引发异常并终止程序。在这种情况下,无法执行优化。

(强调我的)。如果编译器可以(并且确实)假设我们的程序没有 UB,为什么不能执行此优化?

[1]: 延斯·古斯特。现代 C.曼宁,2019,9781617295812.hal-02383654 https://inria.hal.science/hal-02383654


TL:DR:你是对的,这样的优化并不被禁止signed int, 仅适用于float/double,而不仅仅是因为这种情况下的例外。

UB 的原因之一是某些不起眼的机器可能会引发异常。但是打UB是不保证在所有机器上引发异常(除非您使用gcc -fsanitize=undefined,对于 UB 类型,它或 clang 可以可靠地检测到,或者gcc -ftrapv https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html将signed int 溢出的行为定义为捕获)。当编译器通过假设某些事情不会发生而将 UB 视为优化机会时,情况就大不相同了:UB 不是“错误”或“陷阱”的同义词。

有些操作可能会在普通 CPU 上陷入困境,例如未知指针的 deref 以及某些 ISA 上的整数除法(例如 x86,但不是 ARM)。如果您正在寻找编译器可能需要小心的操作,以避免在需要发生的副作用之前或在可能导致抽象机无法到达未定义的分支之前引入异常,那么这些可以作为示例根本没有操作。


有符号整数溢出是 UB,因此在程序执行过程中的任何点(在 C++ 中,根据 C 标准的某些解释),任何事情都可能发生,即使是在为非陷阱机器进行编译时也是如此add指令(像所有现代 ISA 一样)。

某些实现可能会将行为定义为引发异常。如果他们定义where引发异常,那么它将阻止优化;每个加法都需要按照编写的方式进行,这样如果抽象机中的操作溢出,它就会陷入其中。但这将定义行为,与 UB 的含义完全相反绝对零保证 http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html关于你的程序实际上做了什么。

In C, if n3128 is accepted1, any visible side-effects sequenced before the abstract machine encounters UB must happen. But after UB is encountered, literally anything is allowed, including doing I/O. UB doesn't have to fault and stop execution. If a compiler was compiling the += operations with MIPS signed-overflow-trapping add instructions instead of the usual addu, it would be legal to optimize to x+=12 after the intervening code even if it contained I/O operations or other visible side-effects (like a volatile read or write). Even if the x+=5 caused signed overflow UB in the abstract machine, it's fine if the actual behaviour is to trap later (for example when the abstract machine would have done the x+=7 part). As long as it's at or after the abstract machine hit UB, literally anything is allowed. (In C++, it would also be legal to do the possibly-trapping addi $s0, $s0, 12 even before a printf or something, due to the explicit lack of requirements on behaviour even before the first undefined operation, for an execution that does encounter UB. But only if the compiler can prove that printf definitely returns, so in practice this optimization can usually only happen for volatile accesses if at all. But even without retroactive effects, we can either do x+=5 before and x+=7 after, or x+=12 after. Not faulting is valid behaviour for signed overflow, but the abstract machine has done an undefined operation so anything that happens later, like printing and then trapping, or just having the addition wrap, is allowed.)

编译器只需避免在不应该有任何异常的执行路径上引入异常。 (这对于主流 ISA 上的整数加法来说不是问题;大多数甚至没有捕获有符号加法指令,并且针对 MIPS 使用的编译器addu即使是有符号的数学,这样他们就可以自由优化,而且因为历史上程序员不希望陷入困境int math.)

脚注 1:C 与 C++,以及 C UB 应该是“具体”还是“抽象”

See 未定义的行为追溯是否意味着不能保证早期可见的副作用? https://stackoverflow.com/questions/77146088/does-undefined-behaviour-retroactively-mean-that-earlier-visible-side-effects-ar and n3128:驯服恶魔——未定义的行为和部分程序正确性 https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3128.pdf,建议 ISO C 明确指定在抽象机达到未定义操作之前可见的副作用(如 I/O)仍然必须发生。 (当前 ISO C 标准的常见解释将 UB 视为 C++,其中C++ 标准明确允许 https://eel.is/c++draft/intro.abstract#5沿着通往 UB 的必然之路“破坏”东西。)


编译器执行此操作的实际示例

Both int and unsigned可以进行此优化,只有 FP 类型不能,但这也是因为舍入,即使您使用gcc -fno-trapping-math(FP 数学选项)。查看它的实际应用Godbolt https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1AB9U8lJL6yAngGVG6AMKpaAVxYM9DgDJ4GmADl3ACNMYj0AB1QFQlsGZzcPSOjYgV9/IJZQ8K4LTCsbASECJmICBPdPXMtMazji0oJ0wJCwvQUSsoqk6s6mvxastq4ASgtUV2Jkdg4/AgBqGIYAawBSAGYAIVWNAEE5%2Bf5UYxjgf3QIA9UR%2BdWAdm29%2Bef51VuAJm31gBF5gFYNo9di9Fn5lrcfvMuICdsCXm9Vp8Nr87jCni9iJgCJMGK80bt7t9YbDXAxTudDqhjqTyZgLjS8Gc6a8bvcgSCEUjIQCtrCQUtwciofiOR8viiRRisTi8by9oTiXsqLRUEwFkdjMrVQRqCq1Szbg8%2BfCxUKeeyXgKIb9oXK4c9OeL5qi7SDMdjiLjVPiFXsOGNaJw/rxPBwtKRUJxHIsJlNMB91jxSARNP6xssQOt3gA6O4ANkkfw0AA4NFxi3m/gBOSTrfScSQh1MRzi8BQgDTJ1NjOCwJBoFgROhhciUAdD%2BjhZDALhZ0hYABueGmADU8JgAO4AeQijE4SZotAIYXbEGCzeCflKAE997xL8xiNet8FtLUU9xeAO2IItwxaLeYa8FgwSuMAjhiLQ7afvOmAsIYwDiEB854JidQLpg0Hhpgqi1K4x53uQgj5M2tB4MExA3s4WDNgQxB4Cwd5jMqTDAAoa6bjue4wfwggiGI7BSDIgiKCo6jIbouQGEYICmMY5hkcE7aQGMqARIUZKcAAtFu6zzFpVAMKgWl0UwERDkYWnwQQCC8KgGHEPRWDKRAYw1HUdgQA43RVKQPgDJk2TJDEGk%2BcFqQMM0gXDHkBT1H0YXVPk77xY0UWtDkFgJS4lTtH06VDDkbmxtMEgBkGTbIZGHCvBWWkFvMwDIMgULrNm7zzBAuCECQCajLwH5aCM6aZpI2Z/JIebFvmXAaHmU3FlWdaBhwjakKG4bVW2HZdkBPYwIgKCoIOw5kBQEDjqdKDINJM55honaLsumAcduu6hgedDHsQp7nshD43oRANPi%2Bb7WIR36MAQf4Ac2IFgRBtBQYRWDwUYSHhvgaE2BhWG8DheEETBcwkchimUU%2B1EzOGdEMUxfAGGxr1cR9vC8cIojiEJ7OiWoza6NIt2yWY%2BjkS5qnqXE0E6esdkOU5mHwG5yUeZ4XkME4OU9H5GsFUFuRRCFcSJaQhsRXrMXuRpDRdFrvlW6lZQW5lHSNCbrtOwFGVleMkylaM9YcMG63NtVtV5vVkjzDdCFQnm2YaAnnXdUQxB9SMA3dmMCCYEwWDhK5pAZlm2YLXmXB/NNk1/FwlaB2tjGzZ2G12a2Fg7YNaaB%2B8lWbW3nfDaQDkxHYkhAA与 GCC13 和 Clang 16

int sink;    // volatile int sink doesn't make a difference
int foo_signed(int x) {
    x += 5;
    sink = 1;
    x += 7;
    return x;
}
// also unsigned and float versions
# GCC -O3 -fno-trapping-math
foo_signed:                               # input in EDI, retval in EAX
        mov     DWORD PTR sink[rip], 1
        lea     eax, [rdi+12]             # x86 can use LEA as a copy-and-add
        ret
foo_unsigned:
        mov     DWORD PTR sink[rip], 1
        lea     eax, [rdi+12]
        ret
foo_float:                    # first arg and retval in XMM0
        addss   xmm0, DWORD PTR .LC0[rip]     # add Scalar Single-precision
        mov     DWORD PTR sink[rip], 1
        addss   xmm0, DWORD PTR .LC1[rip]     # two separate 5.0f and 7.0f adds
        ret

答案的早期版本,对同一结论提出了一些不同的观点

你是对的;假设x是一个局部变量,所以实际上没有什么可以使用x += 5结果,优化是安全的x+=5; ... ; x+=7 to x+=12对彼此而言signed and unsigned整数类型。

无符号整数数学当然没问题。

在抽象机的任何情况下,有符号整数数学都必须产生正确的结果doesn't遇到UB。x+=12这样做。不能保证有符号溢出会在程序中的任何特定点引发异常,这就是现代 C 中基于不会发生未定义行为的假设的优化的全部要点。对于将遇到 UB 的执行,实际上任何事情都可能在该点之前或之后发生(但请参阅上面的脚注 1:沿着通往 UB 的不可避免的路径“破坏”东西)。

这种优化即使对于转弯也是安全的x-=5; x+=7 into x+=2,其中抽象机可以换行两次(遇到 UB),但 asm 不会换行,因为“碰巧工作”是允许的行为,并且在实践中很常见。 (即使使用 MIPS 捕获add例如,说明。)

如果您使用类似的编译器选项gcc -fwrapv,它将有符号整数数学的行为定义为 2 的补码换行,删除 UB 并使情况与无符号相同。

GCC 有时确实会错过带符号整数数学的优化,因为 GCC 内部不太愿意在汇编中临时创建有符号溢出,而抽象机中不存在这种溢出。当为允许非陷阱整数数学(即所有现代 ISA)的机器进行编译时,这是一个错过的优化。例如,GCC 将优化a+b+c+d+e+f into (a+b)+(c+d)+(e+f) for unsigned int但不是为了signed int没有-fwrapv。 Clang 对于 AArch64 和 RISC-V 都适用,但选择不针对 x86。 (Godbolt https://godbolt.org/#z:OYLghAFBqd5TKALEBjA9gEwKYFFMCWALugE4A0BIEAZgQDbYB2AhgLbYgDkAjF%2BTXRMiAZVQtGIHgBYBQogFUAztgAKAD24AGfgCsp5eiyagA%2BudTkVjVEQJDqzTAGF09AK5smBpwBkCTNgAcp4ARtikIABM5AAO6ErE9kyuHl4G8Yl2Qv6BIWzhkTHW2LbJIkQspESpnt48Vtg22UwVVUS5wWER0VaV1bXpDUr9HQFdBT1RAJRW6O6kqJxcAPQrANQA4s7O6%2BixdmwEAF7YmOuJwIHnAUTrhDQ0EcxE9ACe64Kk60zo66TYFhKITkdbuJiMJRKdZveZglTrAC0NAA7qQWLEAG7rCAopAEVBIdZIIE/P7YR6lO5CdYYUgA2yBKF7GjrIhIbDrIFsaYAUi0AEE1rSjCZaUh0AlsNChJz6EJgOKWAEWVzMJhoV91qF0OzaUDpaC8QSiSpsGxobFSOhQixQu8Lu5Qoj9ocJPyBR7eVEAMw4OiBdYAFXWtw9IcE6AgIZYoJDoTjtMTmET2ETNETwETSGm615AHYAEIe9al/7YIgLJhc72F0K11C1zC17C1mi14C1pC8n3FwUFgAiXv7vvB/uDXt9/vGwbBTEu13D2qq0a5iYTs8ss5Ts7Ts4zs6zs5zeaLJbLAMrpGrLFr9aihcbD%2BbD9bD/bD87D%2B7va9%2BaHgpcLM9DcAArPw3hcDo5DoNwuzAgsSx5r6fDkEQ2hAbMADWIDSFoAB0oH5gAbDIAAcZE%2BqBWgUVEsggVw0j8GwIDUeQkHQbBXD8EoIBaGhGGzHAsCIBAKAYGwsQMBElDUBJUmMJEqCoKKwA8MRWj8TgmIEtgABqBDYCiADysTMNwqF0PQRARLxEChBh5ChAEVRvBZ/DOawpBvMZoS6FS7nkBJHDCMZEJuVB/A4KE7jAM4Ej0LxvBReaxjAJIkXkIQDJ2Ji0qOdg6ilO4NmBbcTSOfQBChOi3muDgjlEKQBAsclsw0EYwBKAZRmmeZyVyMIYgSJwMiDYoKgaI5%2Bj0WlIDmKYlhVaEvGQLMrrJEliLGT6/DoHl9IEDgq0QLMJRlA4EBOIM3igeQfjjPkhQgMRcQJEkQg3axb1ZMknRPT0r3nS0bQDG4dTfcD5SjP93SREDoxfXdIztLDkzw2d8yLKNwFgRBjlces6hkcRiLEdIIppes6n4QRWg4vgxBkMhPo8NM/DoZF0yzByLA4JEp3kDhbEMUx5AsWxHF7dwPF8QJXPkMJyBoOgknSRQVAQPJ6sgFUbCYmRiLKap6maVl2A6UsPUmWZkGWQwNmkHZDmZZ5rmBW73m%2Bf5tiBcFLxhe8jnRbF8X0IlgU4GwaUZdB2VUgQeVJdBhXFaVA3lQx0HLbVbz1cs0FNS17ntZ13WGTb/WWfIw2SGNgjCMoaiaJl%2Bg%2BoYc0LUt1UnetBybdw227TBB3Ncd8BnU0CeXdd4PpFE%2Bb3UwmBo89MSZB9KRz94C8/Zvq9TI0zTQ%2B0X271DQig2MeRw70KNg2kO%2BL/f18TGvmOITjhh4%2BxBPcFypB9aGxYJTMUNM6YM0ICQb43pWbs3ljobm5Beb82oNhVi/FRb40ylxWW/FOaINxlwKIzEMG/xwTLBBmEha4QIkRUi0gKJURomROi38uDDyljBShBCgKK1EuJVWCkZKa21opNAakfQxG0rpa2fU7b8Cso7Z2jlPYRVQmo72AUBr%2B1CuFYO2AYpxQSklVCUcY4FyigQHKid8qZVTqgEqyxUKZ0qtVXO%2BdGrNVanwUuLAupyNtoFBuohxB11kCEpuU1W4GFUvNCwhge4Txgv3IQW0drrD2qPI6%2BU1pH2nt4K6y8voNAejfdGGR3otBKXvFoB9IjDCnhdVoiNt4GAvi01Gj1b7DFaY/dpMNukVLZnMT%2BUgiHgXIZxf%2BxNSbk3WMAZS1MfT4SiJApmMCULwN4UgnCUQyL4QotIaQREZBaGkKzMiWhXpYKmdLbiVg5Y7P4fAMSKs1aKVklrIROtUCSOkRbWRFd5HBIdrZagLtoJqI9i5L2fltGoV0UQQOEU46GNDiYyOqUTCxysTYpOBUiqOPTi44QFVMo51cp4zKRcfF8I6v48uvUgkDRCbXUaET5BRJbtBfQMQ4ld0SStZJG00mDwyciNEGJMRZIiGPXJgsOmOGKW00py96mVN%2Bp9VVtS/pDOeo04%2Bl8%2BkQ0NQUq%2BGremnx1S/S1H9sbjPYZMrhhNZlkwpos1AyzVnrOgSzNmHNBLoJ9HQn0ABOcNeE6LSHzGGsNd1bkusobxfBQb2EkLudwh5OzZgHUSA4aQQA%3D%3D)。同样,这是由于 GCC 由于某种未知原因过于谨慎而错过的优化;这是完全有效的。 2 的补码有符号数学与无符号二进制数学相同,因此是结合律;例如,在优化计算来回绕行但抽象机没有绕行的情况下,最终结果将是正确的。

有符号溢出UB只是抽象机中的东西,不是asm;大多数主流 ISA 甚至没有在溢出时陷入困境的整数加法指令。 (MIPS 确实如此,但编译器不将它们用于int数学,因此他们可以进行优化,产生抽象机中不存在的值。)

半相关:为什么 GCC 不将 a*a*a*a*a*a 优化为 (a*a*a)*(a*a*a)? https://stackoverflow.com/questions/6430448/why-doesnt-gcc-optimize-aaaaaa-to-aaaaaa(答案表明,编译器确实优化了整数数学的三乘,即使是有符号的int.)


FP 异常并不是 float/double 的唯一问题

浮点数学无法进行此优化,因为由于舍入不同,它可能在非溢出情况下给出不同的结果。两个较小的数字都可以向下舍入,而一个较大的数字则可以克服阈值。

例如对于一个数字足够大,最接近的可表示double值是16彼此分开 https://en.wikipedia.org/wiki/Double-precision_floating-point_format#Precision_limitations_on_integer_values, 8将得到一半并舍入到最近的偶数(假设默认舍入模式)。但再少一点,比如7 or 5,将始终向下舍入;x + 7 == x,所以两者57会丢失,但是x+12一次性完成所有操作将跨越驼峰到达下一个可表示的浮点或双精度,产生x+16.

(The magnitude of 1 unit-in-the-last-place (of the mantissa) depends on the exponent of a float/double. For large enough FP values, it's 1.0. For even larger values, e.g. double from 253 to 254 only even numbers are representable, and so on with larger exponents.)

如果您使用 GCC 有缺陷的默认值进行编译-ftrapping-math,它将尝试尊重 FP 异常语义。如果溢出发生两次,它不会可靠地生成 2 个 FP 异常,因此它可能不关心这一点。

但是,是的,与#pragma STDC FENV_ACCESS ON,每个单独的 FP 操作都应该具有可观察到的效果。 (https://en.cppreference.com/w/c/numeric/fenv https://en.cppreference.com/w/c/numeric/fenv)。但如果你不打电话fegetexcept为了实际观察两个操作之间的 FP 异常标志,理论上它们仍然可以被优化if我们可以证明舍入是相同的,因为我认为即使是 ISO CFENV_ACCESS ON应该支持每个捕获操作实际运行的异常/信号处理程序。

例如两个身份操作,例如x *= 1.0;可以折叠为 1,这将引发 NaN 异常。或者x *= 2; x *= 2;可以优化为x *= 4;因为乘以 2 的精确幂不会改变尾数,因此不会导致四舍五入。第一个或第二个乘法是否溢出并不重要+-Inf,这仍然是最终的结果。 (除非Inf * 2引发溢出乘法不会已经引发的异常标志?我不这么认为。)

他们都在同一个方向改变指数,这与x *= 4; x *= 0.5;对于大数可能会溢出到 +Inf,因此不等于x *= 2。另外,如果x *= 0.5; x *= 0.5;产生低于正常的结果,它实际上could尾数右移时舍入两次; IEEE FP 具有逐渐下溢(对指数进行特殊编码的次正规),但非逐渐溢出到 +Inf。

确定优化是否安全x * 0.5 * 0.5 to x *= 0.25超出了这个答案的范围。 GCC 和 clang 没有优化x *= 2.0f; x *= 2.0f; into x *= 4.0f;即使-fno-trapping-math,但我认为这是一个错过的优化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果 C 编译器无法证明缺少 UB,为什么要禁止优化? 的相关文章

随机推荐

  • 如何设置SMO ScriptingOptions以保证表的精确副本?

    我正在尝试做的事情 使用 C 创建 SQL 脚本来创建exact现有表的副本 我的问题 您将如何定义 scriptingOptions 中的选项以确保生成的脚本将创建 100 精确的表副本 有 78 个选项 目前尚不清楚如何执行此操作 最初
  • 将 ODP.NET 12 (VS2012) 连接到 Oracle 数据库 11 时出现 ORA 03134 错误

    当尝试使用 ODP NET 12 从 VS2012 连接到 Oracle 9 2 时 我收到以下消息 ORA 03134 不再支持与此服务器版本的连接 我已经安装了 ODP NET 11 但遇到了同样的错误 尽管与 Toad 的连接正常 有
  • 查询返回没有记录显示在我的网页上

    我有一个网站 我正在其中运行以下代码
  • 如何在node.js中处理stdout

    我试图自动化每次在服务器上测试应用程序和网站时所经历的过程 我目前正在nodejitsu上运行 当我测试了某些东西并且它可以在我的本地计算机上运行时 我要做的下一件事是 打开我的 package json 文件 删除域字段并将名称和子域更改
  • Spring 4 二进制文件下载

    我已经有一段时间没有下载spring了 我正在研究 gradle 但似乎还没有掌握它的窍门 所以我想使用 java Spring 4 和 ant 创建一个新的 spring 框架项目 我似乎找不到下载 Spring 4 二进制文件的地方 他
  • java.lang.ClassNotFoundException:com.mysql.jdbc.Driver。 [复制]

    这个问题在这里已经有答案了 我正在使用 Java Eclipse 连接 MySQL 数据库 但遇到以下错误 错误信息 无法连接到数据库java lang ClassNotFoundException com mysql jdbc Drive
  • 如何使用 JSON 数据递归填充 TreeView

    我有一个winforms树视图 我可以自动读取数据 一个等于key的节点 以及一个等于value的节点 但是当读取对象类型时 它里面的值不会是对象的子对象节点 对象的键 也许我无法很好地解释 这是屏幕截图和我的方法 Layer0 需要位于纹
  • 获取通用接口的所有实现类型

    我试图使用以下代码获取 IEntityModelBuilder 的所有实现 但它返回一个空集合 public class EntityFrameworkDbContext DbContext constructor s and entiti
  • SSL 认证适用于本地主机,但不适用于计算机名称或 IP

    我们有一个在服务器上运行的 Web 应用程序 它通过 XDomainRequest 发布 http 请求 因为 IE9 有很多客户端计算机都有一个控制台应用程序通过套接字侦听器侦听端口 客户打开 Web 应用程序 IE9 浏览器 当他们单击
  • :after 和 ::after 有什么区别? [复制]

    这个问题在这里已经有答案了 它说区别在于 after是CSS2 而 after是CSS3 还有更重要的区别吗 我尝试过谷歌搜索 但冒号似乎放弃了搜索 伪元素在 CSS2 中用单个冒号表示 但在 CSS3 中已更改 为了区分伪类和伪元素 出于
  • 使用 jq 分配多个输出变量

    我正在尝试使用jq解析来自的信息TVDB api https api thetvdb com swagger 我需要提取几个字段并将值分配给我可以继续在我的应用程序中使用的变量bash脚本 我知道我可以通过 bash 轻松地将输出分配给一个
  • Java 脚本警报 R 遇到致命错误。此会话已终止

    我经常使用 RStudio 一切都运行顺利 但最近我的 Windows 严重崩溃 必须恢复到之前的状态 此后 当我打开 RStudio 时 我的项目无法打开广告 反复显示错误Java 脚本警报 R 遇到致命错误 本次会议已终止 我确信在 W
  • Symfony 所有可用内核参数的列表,如 %kernel.debug%

    如何获取可在配置文件中使用的所有内核参数的列表 例如 在 config yml 中 我知道我可以访问 kernel debug 它返回 true 或 false 具体取决于 app php 或 app dev php 文件中 AppKern
  • C 中的双指针和三指针

    我有一个小程序 如下所示 该程序是为了更好地理解 C 中的指针以及变量在内存中的排列方式 include
  • Java Swing JScrollPane 行号故障

    我在 JScrollPane 中有一个简单的 JEditorPane 它在左侧显示行号 它工作得很好 除了当您将窗口移出屏幕并再次将其拉回来时 当您停止拖动时它看起来像这样 有任何想法吗 我是否需要监听移动 拖动事件并在某处调用重绘 重新验
  • 用户警告:Pandas 不允许通过新属性名称创建列

    我被我的熊猫脚本困住了 实际上 我正在使用两个 csv 文件 一个输入文件和另一个输出文件 我想复制两列的所有行并想要进行计算 然后将其复制到另一个数据框 输出文件 各列如下 lat long PHCount latOffset 1 lon
  • 如何将 flutter CameraImage 转换为具有正确颜色和旋转的 png 或 jpg?

    我正在使用camera颤振库和startImageStream控制器的方法 每 X 毫秒我都会收到一个CameraImage输入并希望将其保存为 jpg png 文件 我正在使用一些在网上找到的代码 但它有两个问题 它是灰度的并且没有任何颜
  • 如何在 xampp windows 中使用 CRON?逐步在开发中使用[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 应采取哪些步骤xampp codeigniter 使用 cron 以及如何让 cron 调用我们的函数XAMPP Windows 我们需要下载任何 e
  • React 和多个表单字段

    我正在读书关于 onChange 的文档 http facebook github io react docs forms html controlled components我很好奇如果我的论坛有多个字段 如选择框 复选框 文本区域和输入
  • 如果 C 编译器无法证明缺少 UB,为什么要禁止优化?

    如果 C 程序有未定义的行为 任何事情都可能发生 因此编译器可能会假设任何给定的程序不包含 UB 因此 假设我们的程序包含以下内容 x 5 Do something else without x in the meantime x 7 当然