Is it recommended to use memset before strncpy?

2

Normally when we want to copy the contents of a given string into another string we can use the strncat or strncpy functions.

Using strncat

The use of strncat to copy strings is kind of "wrong", as this function is used to concatenate / join strings and not copy, but it is still possible for this you just have to use the memset function in string and then apply the strncat function thus preventing the destination string from receiving garbage. Here is the code below for a closer look at the thing:

#include <stdio.h>
#include <string.h>

int main(void){

    char foo[15];

    printf("\nFoo (lixo): %s\n", foo);

    memset(foo, 0, 15);

    strncat(foo, "BOING 737", 10);

    printf("\nFoo: %s\n", foo);

    return 0;
}

Using strncpy

#include <stdio.h>
#include <string.h>

int main(void){

    char foo[15];

    printf("\nFoo (lixo): %s\n", foo);

    strncpy(foo, "BOING 737", 10);

    printf("\nFoo: %s\n", foo);

    return 0;
}

Now comes the question: Would it be necessary, for precautionary reasons to avoid junk, to use memset before strncpy ?

    
asked by anonymous 19.07.2018 / 20:48

2 answers

2

That is not the question to be addressed. In cases where the pointer could be used containing garbage, probably the logic of the algorithm / program / function is wrong, and putting a memset there would not make it correct.

In cases where the algorithm is correct without using memset and garbage is never used, then putting memset there will not help at all.

In cases where without memset , the logic is wrong and when adding it, it is correct, so be it. In this case the memset is initializing memory with a lot of zeros. However, it is not possible to generalize and say that this would be a universal solution, although it is certainly frequent.

There are cases where the array should be initialized with something else, such as blanks or a pre-determined text or something else. In these cases, adding memset probably will not help you.

In the end, the issue is reduced in how this memory should be initialized. memset is just one of the ways to boot, but it's not the only one. The algorithm / program / function should ensure that the memory to be used has been initialized, but this is no reason to aggressively initialize anything even if it is not needed.

As for memset + strncat or strncpy , strncpy should perform better, but this will only be measurable and meaningful if it is within a loop that runs at least a few million times or if it is something that you use to process quantities of text equivalent to whole books and that is not something that has processing time dominated by some other more complex operation. That is, it will probably have no significant difference.

However, the main reason for using strncpy is that your intent is much clearer for anyone reading the code (even if it's you months or years later). Using memset + strncat is somewhat odd.

If it is really necessary to zero the entire buffer before using it, I would recommend using memset + strncpy . But if it is not necessary to zero it, just that anything after the null terminator is ignored, then strncpy alone would be enough.

    
19.07.2018 / 21:10
1

The strncpy documentation answers your question.

Citing just the parts that matter:

  

If the end of the source C string (...) is found before characters have been copied, destination is padded with zeros until a total of characters have been written to it

Translating:

  

If the string being copied has fewer characters than the specified size, zeros are placed at the end until they are sized.

These zeros end up as terminators, even if the original string does not, so you will never see any garbage in the string, since functions that work on strings stop at the first terminator.

  

In the null-character is implicitly appended to the end of the destination if it is longer than one num. Thus, in this case, destination shall not be considered to be null terminated C string (...).

Translating:

  

No caratere terminator is added at the end of the destination if the string size is greater than the specified amount. And for this reason the resulting string will not be considered a C string ending with null.

That is:

  • If you copy less than the indicated size, you will never see garbage, assuming you copy a valid string with a terminator.
  • If you copy more characters than the indicated size, you will usually have an unfinished string, so you get garbage.

Examples:

#include <stdio.h>
#include <string.h>

int main(void){

    //Teste para copia com menos caracteres que o numero indicado
    char foo2[] = "outra string!!!";
    printf("\nFoo (lixo): %s\n", foo2); //Foo (lixo): outra string!!!
    strncpy(foo2, "BOING 737", 10);
    printf("\nFoo: %s\n", foo2); //Foo: BOING 737

    //Teste para copia com mais caracteres que o numero indicado
    char foo[] = "outra string!!!"; 
    printf("\nFoo (lixo): %s\n", foo); //Foo (lixo): outra string!!!
    strncpy(foo, "BOING 737", 5);
    printf("\nFoo: %s\n", foo); //Foo: BOING string!!!

    return 0;
}

I applied an initial string to make testing more evident.

Test Yourself on Ideone

Conclusion:

If you are sure that you are copying a complete string (with a terminator) and the size is less than or equal to the one indicated in strncpy then you do not need to memset . If you are not sure about this, it is best to play it safe and apply memset .

It's worth remembering that a lot, if not all reading functions, such as scanf , put the terminator in the read string, making it unnecessary to do any type of memset beforehand.

    
19.07.2018 / 23:38