这是来自Codewars挑战的,因此我将在此函数中省略不必要的代码。基本上如果是n <= 1
,我需要返回一个空字符串。
char* sc(int n)
{
if(n > 1) {
//irrelevant code
}
//return strdup("");
return "";
}
如果要传递的值为-1
,则当我使用return "";
时会收到“测试崩溃”消息,但是当我使用return strdup("");
时,我可以通过测试。只是想知道为什么会这样?
编辑: 这就是调用函数的方式。这只是最后一次失败的测试。
#include <criterion/criterion.h>
#include <string.h>
char* sc(int);
void dotest(int n, const char* expect)
{
char* actual = sc(n);
cr_expect(!strcmp(actual, expect), "Expected: '%s', got: '%s'\n", expect, actual);
free(actual);
}
Test(the_multiply_function, should_pass_all_the_tests_provided) {
dotest(2,"Aa~ Pa! Aa!");
dotest(6, "Aa~ Aa~ Aa~ Aa~ Aa~ Pa! Aa!");
dotest(7, "Aa~ Aa~ Aa~ Aa~ Aa~ Aa~ Pa!");
dotest(10, "Aa~ Aa~ Aa~ Aa~ Aa~ Aa~ Aa~ Aa~ Aa~ Pa!");
dotest(1, "");
dotest(-1, "");
}
答案 0 :(得分:2)
这个挑战似乎要求该函数返回一个动态分配的字符串。可以从以下位置看到:
$pdf->Output('I', 'filename.pdf')
因此,该函数必须使用char* actual = sc(n);
...
free(actual); // free is for dynamic allocated memory
类型的函数来分配字符串。 malloc
就是这样做的,即它会分配动态内存,并将字符串(即此代码中的strdup
)复制到该内存中。
仅执行""
会将地址返回到具有静态存储持续时间(即某些无法释放的内存)的字符串(即return "";
)。在具有静态存储持续时间的内存上调用""
会导致未定义的行为,这可能会导致程序崩溃。
答案 1 :(得分:2)
函数sc()返回字符串常量“”。字符串常量会自动分配到单独的内存中。
sc()是此字符串常量的返回地址。在do test()中,您将地址存储在实际变量中并释放它。
您不应该释放该内存。只需删除free(actual);
。
答案 2 :(得分:2)
对于free()
的使用,摘自C11
第§7.22.3.3章(强调我的)
free
函数导致ptr
指向的空间被释放,即 可用于进一步分配。如果ptr
为空指针,则不执行任何操作。否则,如果 该参数与内存管理器先前返回的指针不匹配 函数,或者如果通过调用free
或realloc
释放了空间,则 行为是不确定的。
,还有strdup()
(再次是我的重点)
strdup()
函数返回一个指向新字符串的指针,该字符串与字符串s
重复。 新字符串的存储空间是通过malloc()
获取的,可以通过free()
进行释放。
因此,当您使用return strdup("");
时,返回的指针可以传递给free()
-一切正常。
OTOH,通过说return "";
,您将返回一个指向字符串文字第一个元素的指针,该指针不适合传递给free()
,如上所述,它调用{ {3}}。
崩溃或分段错误是UB的许多副作用之一。 。