简体   繁体   中英

Why use memset in this case

I have inherited some code from a previous developer that has retired. My question is specifically the use of memset in the following scenario. Not being a c programmer, I am wondering why memset was used in this particular case, where the next line of code stores the value in the variable that was just set to all 0 by memset. Is there a reason to use memset right before strcpy?

switch(argc)
{
    case 1  :
        printf("\nCommand: %s \n",argv[0]);
       break;
    case 2  :
        memset(program_input_string,0,sizeof(program_input_string));
        strcpy(program_input_string,argv[1]);
        printf("\nCommand: %s [%s] \n",argv[0],argv[1]);
       break;
    default :
        printf("\nCommand: %s \n",argv[0]);
}

The truth is there is zero reason to use memset + strcpy in this case. In fact if the programmer wanted to ensure that the remaining bytes were zeroed, then strncpy with a conditional for testing if the string fit in entirety into the buffer should have been used:

strncpy(program_input_string, argv[1], sizeof program_input_string);

// if the last character in the array is not '\0', it means that the
// string did not fit into the array in its entirety, and perhaps 
// the only sensible course of action is to abort the program...
if (program_input_string[sizeof program_input_string - 1] != '\0') {
    fputs("The argument was too long!", stderr);
    exit(1);
}

This has two obvious advantages: it does not set the initial sequence to zero needlessly and it cannot overrun the input buffer - and if the buffer overrun were to happen it will exit with a sensible error message and exit code.


Thus the definite answer to the question "why was this construct used" would be the all-too-common "programmer incompetence".

It's probably unnecessary, but you should check carefully before you delete it.

The memset() ensures that any bytes after the terminal \0 are zeroed out. If program_input_string is always read as a string and code always stops when it hits \0 then what comes after doesn't matter.

It could be useful if there's code that reads from the entire buffer, trailing bytes included. For example, if all sizeof(program_input_string) bytes were copied into a network packet and sent over the wire you wouldn't want to transmit uninitialized bytes. In that case, zeroing out the buffer would be worthwhile.

I am wondering why memset was used in this particular case, where the next line of code stores the value in the variable that was just set to all 0 by memset. Is there a reason to use memset right before strcpy?

The particular memset() call presented sets every byte of the destination array to 0. The strcpy() call, when successful, overwrites only as many bytes as are in the argv[1] string, including the terminator, which may be fewer. Whether this distinction is in fact important to the program is impossible to determine from the code presented.

Note also that the code presented is subject to buffer overrun -- it is in fact an example of one of the canonical cases for that issue. If argv[1] is longer than the destination array then undefined behavior ensues.

In this case the call of memset is redundant. You may just write

strcpy(program_input_string,argv[1]);

because the function strcpy copies also the terminating zero in the destination string.

As an idea sometimes a character array need to contain several strings. In this case two consequitive zeroes mean the end of the set of strings stored in the character array. So it is required to initialize the array with zeroes.

Let's assume that the array program_input_string already contains strings

ABC\0DEF\0\0

then if to copy string E you will get

E\0C\0DEF\0\0

As it is seen the result is not what was expected. Now the array contains a set of three strings instead of one string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM