They are similar functions, but what is the exact difference between them? The Linux documentation states:
Note: Use kmemdup_nul() instead if the size is known exactly.
They are similar functions, but what is the exact difference between them? The Linux documentation states:
Note: Use kmemdup_nul() instead if the size is known exactly.
Both functions allocate the needed memory through kmalloc() and then place a NUL terminator at the end of the allocated buffer. The only difference between the two is that kstrndup() first calls strnlen() to calculate the length of the string and therefore the needed size, thus scanning the string.
You can see kmemdup_nul() as an optimized version of kstrndup(). If you already know the length of the string, you can avoid the initial scanning and just use kmemdup_nul() passing in the length as argument. This saves time since the string doesn't need to be scanned, and it's the reason why you see that note.
Moreover, kstrndup() saves space if the string is shorter than max, so in case you don't know the length of the string, even though kmemdup_nul() would work as well, you might want to call kstrndup() instead to potentially save space.
You can clearly see from the code that the only difference between the two functions is the call to strnlen(). Here's the source code, from mm/util.c:
/**
* kstrndup - allocate space for and copy an existing string
* @s: the string to duplicate
* @max: read at most @max chars from @s
* @gfp: the GFP mask used in the kmalloc() call when allocating memory
*
* Note: Use kmemdup_nul() instead if the size is known exactly.
*
* Return: newly allocated copy of @s or %NULL in case of error
*/
char *kstrndup(const char *s, size_t max, gfp_t gfp)
{
size_t len;
char *buf;
if (!s)
return NULL;
len = strnlen(s, max);
buf = kmalloc_track_caller(len+1, gfp);
if (buf) {
memcpy(buf, s, len);
buf[len] = '\0';
}
return buf;
}
EXPORT_SYMBOL(kstrndup);
/**
* kmemdup_nul - Create a NUL-terminated string from unterminated data
* @s: The data to stringify
* @len: The size of the data
* @gfp: the GFP mask used in the kmalloc() call when allocating memory
*
* Return: newly allocated copy of @s with NUL-termination or %NULL in
* case of error
*/
char *kmemdup_nul(const char *s, size_t len, gfp_t gfp)
{
char *buf;
if (!s)
return NULL;
buf = kmalloc_track_caller(len + 1, gfp);
if (buf) {
memcpy(buf, s, len);
buf[len] = '\0';
}
return buf;
}
EXPORT_SYMBOL(kmemdup_nul);