我有大约 40 个 git 存储库,其中大多数都有一个.git-blame-ignore-revs
用于与git blame
. blame.ignorerevsfile=.git-blame-ignore-revs
因此,我没有使用 本地配置,而是将其应用到我的全局git 配置中。
但是,少数没有此类文件的存储库会受到它的影响:git blame
在它们上运行会导致fatal: could not open object name list: .git-blame-ignore-revs
.
有没有办法告诉 git 读取此类文件(如果存在),否则忽略它?这将是理想的:设置简单,但如果不存在这样的文件也不引人注目。
注意:拥有可选 文件很有用的另一个原因.git-blame-ignore-revs
是,几乎所有 git 存储库都是在没有这样的文件的情况下创建的,只有在稍后才会添加它。然而,当二分旧的提交时,我们最终可能会返回到文件存在之前的touch
某个点,然后我们必须完成二分,然后再次删除它才能返回到 HEAD 提交。即使我对文件使用本地配置,这种极其烦人的情况仍然会发生。出于这个原因,我确实认为默认行为应该是忽略该文件(如果它不存在)。
在我的/usr/include
目录中,至少有两种#define NULL 0
为C++代码1量身定制的变体:
#define NULL 0 // from rpc/types.h
#define NULL (0) // from libio.h
Run Code Online (Sandbox Code Playgroud)
我觉得必须有一个反例,第一个不安全,但我无法生产它.
否则,是否有一些令人信服的论点,说明为什么在这种情况下不包括括号是安全的(例如,非正式的"正确性证明")?
1即,不包括变量#define NULL ((void*)0)
,它对C有用但在C++中无效.
在某些程序中运行addr2line时,我会在行尾给出一个"鉴别器N"注释:
main at /tmp/nsievebits.c:56 (discriminator 3)
手册页没有提到它,快速谷歌搜索似乎主要表明源代码文件,没有明确的解释.这是一些故意无证的功能吗?更重要的是,我应该担心吗?
以下程序由于未定义的行为(尝试修改字符串文字)而引发系统分段错误:
int main() {
char *s = "immutable";
s[0] = 'a';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
尽管如此,似乎绝对没有办法告诉GCC/Clang甚至发出最轻微的警告(-Wall -Wextra -pedantic -std=c11
不做任何事情).
特别是对于初学者来说,这种情况对于告知有用.即使对于非初学者,在一些稍微不那么明显的情况下,它可能会有所帮助:
void f(char *s) {
s[0] = '0';
}
int main() {
char *s = "immutable";
f("literal"); // oops
f(s); // oops
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此外,这将有助于const
在C编程中强制实施一些文化.
为什么故意忽视此类案件?标准是否主动禁止在这种情况下发出诊断,或者主要是为了向后兼容(现在尝试强制执行它们会产生太多警告)?
我试图说服(引用C99标准的具体部分)一位同事,以下是未定义的行为:
int *p = malloc(1);
p[0] = 0;
Run Code Online (Sandbox Code Playgroud)
但我无法在标准中找到明确确保未定义的具体部分.我正在寻找标准中从这些线到结论的逻辑步骤:未定义的行为.它是从第一行转换void *
到int *
第一行吗?第二行的作业?
我能找到的唯一相关部分malloc
是它返回一个适当对齐的指针(7.20.3):
如果分配成功,则返回指针,以便将其分配给指向任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(...)
我试着在标准中寻找空间,但是由于空白和其他词汇问题,噪音太大了.
我经常读到异常有点慢,如果性能是一个问题应该避免(例如,在Java,F#等).这是否适用于常见的OCaml函数,例如Hashtbl.find
,返回未找到元素的异常?
特别是,如果我希望我的应用程序有效,我应该总是使用,例如,Hashtable.mem
在调用之前测试元素成员资格Hashtbl.find
吗?或者mem
功能的额外比较是否会对性能产生负面影响?
我有一个包含了一个ELF 32位x86文件.eh_frame
部分,尽管我尝试1将其删除.
我想删除该.eh_frame
部分,而不触及其他部分中的任何符号,包括未使用的符号.
strip
似乎没有选项--remove-only
,它总是最终修改其他部分.
如何在不修改文件中的任何其他内容的情况下删除单个ELF部分?
1正如其他问题中所建议的,我尝试了几种变体gcc-3.4.3 -fomit-frame-pointer -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables
,但该.eh_frame
部分始终存在.这可能是因为我必须使用旧的GCC(3.4.3)...源文件本身不包含任何可能需要这些部分的特殊内容:int main() { return 0; }
.
GCC 9最近__LINE__
在某些情况下更改了指令的行为。下面的程序说明了此更改:
#include <stdio.h>
#define expand() __LINE__
int main() {
printf("%d\n",expand(
));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
由于宏expand()
(扩展为__LINE__
)跨越多行,因此GCC最多8.3(而Clang最多8.0)考虑了扩展的最后一行的编号print 5
。但是,GCC 9会考虑第一行并打印4。
(Godbolt链接:https://godbolt.org/z/3Nk2al )
C11标准关于的确切行为不是很精确__LINE__
,除了:
6.10.8预定义的宏名称
在以下子节中列出的预定义宏的值(
__FILE__
和除外__LINE__
)在整个转换单元中保持不变。(...)
6.8.10.1强制宏
以下宏名称应由实现定义:
(...)
__LINE__
当前源行的假定行号(在当前源文件中)(整数常量)。
我认为这意味着确切的值是实现定义的,因此不能期望其值在不同的编译器版本或不同的编译器中保持不变。还是在标准的其他地方对这种效果有一些争论?
例如,可以说只要源本身没有变化,当前源行的假定行号就应该稳定吗?
我正在使用ocamldebug(使用OCaml 4.02.1),我正在尝试在特定模块内的某处设置断点,但我得到的只是一个有用的错误消息: Can't find any event there.
作为一个例子,这里是函数1的摘录,我想设置一个断点,如ocamldebug所列:
(ocd) list Value.Eval_slevel 79 83
79
80 let slevel stmt = match slevel with
81 | Per_stmt_slevel.Global i -> i
82 | Per_stmt_slevel.PerStmt f -> f stmt
83
Run Code Online (Sandbox Code Playgroud)
我尝试了几个break
命令的变种,但每次都得到相同的结果:
(ocd) break @ Value.Eval_slevel 80 // module + line number
Can't find any event there.
(ocd) break @ Value.Eval_slevel 80 21 // module + line + column
Can't find any event there.
(ocd) break @ Value.Eval_slevel # 3335 // …
Run Code Online (Sandbox Code Playgroud) 我想了解以下代码是否(总是,有时或从不)根据C11明确定义:
#include <string.h>
int main() {
char d[5];
char s[4] = "abc";
char *p = s;
strncpy(d, p, 4);
p += 4; // one-past end of "abc"
strncpy(d+4, p, 0); // is this undefined behavior?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
C11 7.24.2.4.2说:
strncpy函数从s2指向的数组复制不超过n个字符(空字符后面的字符不被复制)到s1指向的数组.
请注意,这s2
是一个数组,而不是一个字符串(所以当p == s+4
没有问题时缺少null-terminator ).
7.24.1(字符串函数约定)适用于此(强调我的):
如果声明为size_t n的参数指定了函数数组的长度,则在调用该函数时,n的值可以为零.除非在本子条款中对特定函数的描述中另有明确说明,否则此类调用上的指针参数仍应具有有效值,如7.1.4中所述.在这样的调用中,定位字符的函数不会发生,比较两个字符序列的函数返回零,复制字符的函数复制零个字符.
上述7.1.4的相关部分是(强调我的):
7.1.4库函数的使用
除非在以下详细说明中另有明确说明,否则以下每个语句均适用:如果函数的参数具有无效值(例如函数域外的值,或程序地址空间外的指针,或者一个空指针,或指向不可修改的存储的指针,当相应的参数不是const限定的)或一个类型(提升后),具有可变数量的参数的函数不期望,行为是未定义的.如果一个函数参数被描述为一个数组,那么实际传递给该函数的指针应该具有一个值,使得所有地址计算和对象的访问(如果指针确实指向这样一个数组的第一个元素,这将是有效的)事实上是有效的.
我在解析最后一部分时遇到了一些麻烦.n == 0
如果我可以假设我的实现在这种情况下不会计算任何地址,那么"所有地址计算和对对象的访问"似乎很容易满足.
换句话说,在严格解释标准时,我是否应该总是拒绝该计划?我应该一直允许吗?或者它的正确性是否依赖于实现(即,如果实现在检查之前计算第一个字符的地址n
,那么上面的代码有UB,否则它没有)?