Strncpy leading to segmentation error

I just messed around with strncpy.

My program is as follows

typedef struct { char from_str[10]; }test; main () { test s1; memset(&s1,0,sizeof(test)); char src[10]="himansh"; char dest[10]; memset(dest,0,10); src[3]='\0'; printf("src is %s and strlen is %d \n", src,strlen(src)); fflush(stdout); strncpy(s1.from_str,src,100); printf("s1.from_str is %s , src is %s \n", s1.from_str,src); return 1; } 

Here, before doing strncpy, I added the character "\ 0" to the string "src", the length of the string "src" becomes 3, the target array is 10. But in strncpy I set the number of bytes copied as 100.

This means that my original NULL string is complete. Now strncpy, like any string function, should try to copy only 3 bytes, even if the number of bytes I provide is more than 3 (in this case 100). He does this, but I also get a segmentation error.

My result is shown below.

 src is him and strlen is 3 s1.from_str is him , src is him Segmentation fault (core dumped) 

Why is this segmentation error happening here.

Can anyone help me here.

+8
c segmentation-fault strncpy
source share
4 answers

I could point you to man pages, websites, etc., but ultimately it is important that the C standard itself. As part of the standard runtime library, usage and behavior are defined in C99-Β§7.23.2.4 as follows :

 #include <string.h> char *strncpy(char * restrict s1, const char * restrict s2, size_t n); 

Description The strncpy function copies no more than n characters (characters that follow a null character are not copied) from the array pointed to by s2 to the array pointed to by s1. If copying occurs between overlapping objects, the behavior is undefined. If the array pointed to by s2 is a string that is shorter than n characters, null characters are added to the copy in the array pointed to by s1 until all n characters are written.

Returns The strncpy function returns the value s1.

There is significant implied information here: the most important of them: strncpy() will NOT terminate your target string with a null character if the length of the source string (not including its zero character terminator) meets or exceeds the specified length of the destination buffer).

In addition, although this is clearly indicated in the standard (see above), it continues to confuse me how many engineers DO NOT know that strncpy() tail fills the buffer of the target string with null characters until the specified length n is reached when the length of the original Lines are smaller than the size of the destination buffer. This makes the following undeniable conclusion:

The strncpy() API ALWAYS writes n characters to the address referenced by the destination buffer.

In your case, since the target buffer has a width of only 10 characters, you write 90 additional characters that have passed through a certain end of the recorded memory, and thus, go to the country of behavior undefined .

At this point, you should ask yourself: "So what to use?" There is perhaps a fundamental use case. It allows you to copy up to n characters into the target buffer with predictability, knowing that you will not overflow n characters. Period. Ultimately, however, you need a zero-terminated string, so the proper use is:

 char dst[ N ]; strncpy(dst, src, N-1); dst[N-1] = 0; 

where n is the fixed length of the dst buffer in characters and is greater than or equal to 1 . Note that dst can be the most dynamic allocated memory pointer possible:

 char *dst = malloc( N * sizeof(char) ); strncpy(dst, src, N-1); dst[N-1] = 0; 

With the above, you will always have a null-terminated string in dst . If the length of the source string is less than the specified length of the destination buffer, strncpy() will fill the rest of the buffer with null characters as long as the total number of characters with character-interpreted characters-character-characters is n , and the final statement is redundant. If the length of the source string is equal to or greater than the length of the destination buffer, strncpy() stop copying when the N-1 characters are reached, and the end statement sets the null character at the end of the buffer. This results in a prefix string to β€œcut” the source source, but most importantly, it ensures that you DO NOT exceed the bounds of the destination buffer with a later call to the API string that the terminator scans.

The usefulness of the above method is always controversial. I'm a C ++ guy, so std::string keeps my happy self from all this madness. But the reality is this: sometimes you don't care if src not completely copied to dst ; sometimes you don’t do it. Utility is very situationally dependent. For presenting string data in the user interface, this will not (probably). For copying the string used for critical data, a partial prefix substring will not be acceptable. When the police issue an arrest warrant to Joseph Johnson Jr., there will be an explanation when his father (Joseph Johnson) will be sent to jail because the buffer name of the warrant software was only 15 characters long.

All of this, your segmentation error comes down to this statement:

 strncpy(s1.from_str,src, 100); // length parameter is wrong. 

Call up the bold statement above: " strncpy() will ALWAYS write n characters to the address pointed to by the destination buffer." . This means that the code above will always write 100 characters to the target buffer, which in your case has a width of only 10 characters, thus undefined behavior and probability of kera-boom .

Fix this by doing the following if the destination buffer is an array of characters of fixed length:

 strncpy(s1.from_str,src, sizeof(s1.from_str)/sizeof(s1.from_str[0])-1); s1.from_str[ sizeof(s1.from_str)/sizeof(s1.from_str[0])-1 ] = 0; 

See previous use for how to do this for a dynamic string of length `N characters.

+13
source share

From http://www.cplusplus.com/reference/cstring/strncpy/

char * strncpy (char * destination, const char * source, size_t num);

Copy characters from string Copies the first few characters of the source to the destination. If the end of the line of source C (which is signaled by a null character) is detected before the number of characters is copied, the destination is filled with zeros until the total number of characters has been written on it.

Thus, although the length of the source string is less than the size of the size of the target buffer, but due to the strncpy behavior, it tries to overlay the remaining characters beyond the size of the target buffer, causing a segmentation error

Instead of copying more than 100 characters, the size should be equal to the maximum size allowed in the destination buffer, so you could write

 strncpy(s1.from_str,src,sizeof(s1.from_str)/sizeof(s1.from_str[0]) - 1); Actual size -1 to accomodate the null terminator 

or better to write the _countof macro

 #define _countof(s) (sizeof(s)/sizeof(s[0])) ................ strncpy(s1.from_str,src,_countof(s1.from_str) - 1); 
+5
source share

See: http://www.manpagez.com/man/3/strncpy/

The stpncpy () and strncpy () functions copy no more than n characters from s2 to s1. If s2 is less than n characters, the remainder of s1 is filled with `\ 0 'characters. Otherwise, s1 does not complete.

The remainder is filled ....

So:

 strncpy( s1.from_str, src, 10 ); 
+1
source share

strncpy(s1.from_str,src,100);

Why do you use 100 in your function, from_str and src have 10 consecutive bytes, but you copy 100 bytes, which leads to seg. malfunction.

use it

strncpy(s1.from_str,src,10);

0
source share

All Articles