小编ano*_*nol的帖子

git Blame 带有可选的ignorevsfile

我有大约 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 提交。即使我对文件使用本地配置,这种极其烦人的情况仍然会发生。出于这个原因,我确实认为默认行为应该是忽略该文件(如果它不存在)。

git git-blame

30
推荐指数
1
解决办法
7187
查看次数

这个无括号的C预处理器定义是否安全?

在我的/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++中无效.

c++ c-preprocessor

27
推荐指数
4
解决办法
1625
查看次数

addr2line中的"鉴别器"是什么?

在某些程序中运行addr2line时,我会在行尾给出一个"鉴别器N"注释:

main at /tmp/nsievebits.c:56 (discriminator 3)

手册页没有提到它,快速谷歌搜索似乎主要表明源代码文件,没有明确的解释.这是一些故意无证的功能吗?更重要的是,我应该担心吗?

c c++ addr2line

21
推荐指数
1
解决办法
6218
查看次数

为什么C编译器不警告文字字符串不兼容的类型?

以下程序由于未定义的行为(尝试修改字符串文字)而引发系统分段错误:

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编程中强制实施一些文化.

为什么故意忽视此类案件?标准是否主动禁止在这种情况下发出诊断,或者主要是为了向后兼容(现在尝试强制执行它们会产生太多警告)?

c string compiler-warnings string-literals language-lawyer

18
推荐指数
2
解决办法
453
查看次数

证明"int*p = malloc(1); p [0]"是未定义的行为

我试图说服(引用C99标准的具体部分)一位同事,以下是未定义的行为:

int *p = malloc(1);
p[0] = 0;
Run Code Online (Sandbox Code Playgroud)

但我无法在标准中找到明确确保未定义的具体部分.我正在寻找标准中从这些线到结论的逻辑步骤:未定义的行为.它是从第一行转换void *int *第一行吗?第二行的作业?

我能找到的唯一相关部分malloc是它返回一个适当对齐的指针(7.20.3):

如果分配成功,则返回指针,以便将其分配给指向任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(...)

我试着在标准中寻找空间,但是由于空白和其他词汇问题,噪音太大了.

c malloc language-lawyer

15
推荐指数
4
解决办法
1711
查看次数

OCaml异常表现

我经常读到异常有点慢,如果性能是一个问题应该避免(例如,在Java,F#等).这是否适用于常见的OCaml函数,例如Hashtbl.find,返回未找到元素的异常?

特别是,如果我希望我的应用程序有效,我应该总是使用,例如,Hashtable.mem在调用之前测试元素成员资格Hashtbl.find吗?或者mem功能的额外比较是否会对性能产生负面影响?

performance f# ocaml

12
推荐指数
2
解决办法
2246
查看次数

如何删除特定的ELF部分,而不剥离其他符号?

我有一个包含了一个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 elf objcopy

12
推荐指数
1
解决办法
7225
查看次数

是否可以保证__LINE__指令的一致性?

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__ 当前源行的假定行号(在当前源文件中)(整数常量)。

我认为这意味着确切的值是实现定义的,因此不能期望其值在不同的编译器版本或不同的编译器中保持不变。还是在标准的其他地方对这种效果有一些争论?

例如,可以说只要源本身没有变化,当前源行假定行号就应该稳定吗?

c language-lawyer predefined-macro c-preprocessor

11
推荐指数
1
解决办法
146
查看次数

无法在ocamldebug中设置断点:"在那里找不到任何事件."

我正在使用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)

debugging ocaml breakpoints

9
推荐指数
1
解决办法
364
查看次数

带有一个过去指针的strncpy(d,s,0)

我想了解以下代码是否(总是,有时或从不)根据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,否则它没有)?

c language-lawyer

9
推荐指数
1
解决办法
451
查看次数