我正在调整class MyDomain {
String test
static constraints = {
test blank: false, nullable: false
id blank: false, validator: {value, command ->
if (Environment.current == Environment.TEST) {
//do validation for not allowing more than 100 records
if (MyDomain.count() > 100) return ['too.many.records']
}
}
}
,我遇到一个非常奇怪的案例(至少对我而言)。这是代码:
basename
第一个char buffer[300];
char* p;
strcpy(buffer, "../src/test/resources/constraints_0020_000");
printf("%d\n", strcmp(basename("../src/test/resources/constraints_0020_000"), "constraints_0020_000")); //works as expected
printf("assert testBasename02");
printf("%d\n", strcmp(basename(buffer), "constraints_0020_000") == 0);
printf("done 1\n"); //goes in segmentation fault
printf("%d\n", strcmp(basename(&buffer), "constraints_0020_000") == 0);
printf("done 2\n"); //goes in segmentation fault
printf("%d\n", strcmp(basename(&buffer[0]), "constraints_0020_000") == 0);
printf("done 3\n"); //goes in segmentation fault
p = malloc(strlen("../src/test/resources/constraints_0020_000") +1);
strcpy(p, "../src/test/resources/constraints_0020_000");
printf("%d\n", strcmp(basename(p), "constraints_0020_000") == 0); //works as expected
free(p);
printf("all done\n");
完全是例外;这是第二个令我困惑的问题:为什么缓冲区会出现分段错误?我尝试以不同的方式对缓冲区进行编码,但结果是一样的。
我当然可以忍受这种行为,但是......我真的不明白strcmp
如果我给他一个basename
或一个缓冲区(最后是也是const char*
)。
是否有解释此行为的文件?只有我吗?我试图寻找解释,但我找不到任何解释。
这是我的电脑规格(如果你需要):
答案 0 :(得分:4)
根据man page,
错误
在这些函数的POSIX版本的glibc实现中,它们修改了它们的参数,并在使用类似
"/usr/"
的静态字符串调用时发生了段错误。 [...]
基本上,
basename("../src/test/resources/constraints_0020_000")
调用调用undefined behavior,因为这是尝试修改字符串文字。
注意:如手册页中所述,需要更改单词。读它就好了,
在这些函数的POSIX版本的glibc实现中,它们修改了它们的参数,并且当使用类似
"/usr/"
的静态字符串调用时,调用未定义的行为。 [...]
分段错误是UB的副作用之一,但不是唯一的副作用。
FWIW,尝试修改字符串文字本身会调用UB。引用C11
,章节§6.4.5,字符串文字
[...]如果程序试图修改这样的数组,行为是 未定义。
编辑:
正如后续评论中所讨论的,另一个问题是缺少头文件。你需要
#include <libgen.h>
添加,以便获得函数basename()
的前向声明。
答案 1 :(得分:0)
每https://docs.mongodb.com/manual/reference/operator/update/setOnInsert/#op._S_setOnInsert:
basename()
函数可以修改path
指向的字符串, 并且可以返回指向内部存储的指针。返回的指针 可能无效或存储可能被a覆盖 随后致电basename()
。返回的指针也可能是 如果调用线程被终止,则无效。
dirname()和 basename()都可以修改内容
path
,因此可能需要在调用其中一个时传递副本 这些功能。
您使用静态字符串调用basename()
,这可能是只读的,因此当basename()
尝试修改字符串时会导致SEGV。