Advantages of strncmp over strcmp?

你。 提交于 2019-11-29 12:34:01

问题


Seems strncmp is usually recommended than strcmp, what are the advantages? I think it could be related to security. If this is the case, is it still applicable if one of the input string is known to be literal constant, like "LiteralString"?

UPDATE: I mean under the same user scenario where whole strings need to be compared, and strncmp can be used as below. I am wondering it makes sense or not.

strncmp(inputString, "LiternalString", strlen("LiternalString"));

回答1:


The problem with strcmp is that sometimes, if by mistake, arguments that are passed are not valid C-strings (meaning that p1 or p2 is not terminated with a null character i.e. not NULL-terminated String), then, strcmp continues comparing until it reaches non-accessible memory and crashes or sometimes results to an unexpected behaviour.

Using strncmp you can limit the search, so that it doesn't reach non-accessible memory.

But, from that it should not be said that strcmp is insecure. Both the functions works well in the way they are intended to work. Programmer should read man page for that function before using it and must be sincere enough when passing parameters to such library functions.

You can also read THIS which contains an almost similar question.




回答2:


strncmp does not have "advantages over strcmp"; rather they solve different problems. strcmp is for determining if two strings are equal (and if not, possibly how to order/sort them with respect to each other). strncmp is (mainly) for determining whether a string begins with a particular prefix. For example:

if (strncmp(str, "--option=", 9)==0)

will determine if str begins with "--option=". This cannot be achieved by strcmp without either modifying the string to be checked (which may not be a valid operation) or making a useless copy of it. It also cannot be achieved with memcmp unless you already know str points to an object at least 9 bytes in length; otherwise the call to memcmp would have undefined behavior.

There are other usage cases for strncmp too, such as working with non-C-string data.




回答3:


It all depends on your use-cases. Use strncmp if you only need to compare a fixed number of characters, use strcmp if you need to compare a whole string.

That's about it.




回答4:


Just post an anti-strncmp use case here. Think about the following code.

#include <stdio.h>
#include <dirent.h>

int main()
{
    //I want to list all files under current folder, include hidden files.
    DIR *dir;
    struct dirent *dp;
    char * file_name;
    dir = opendir(".");
    while ((dp=readdir(dir)) != NULL) {
        printf("debug: %s\n", dp->d_name);
        if ( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") )
        //It doesn't work if you replace strcmp with strncmp here.
        //if ( !strncmp(dp->d_name, ".", 1) || !strncmp(dp->d_name, "..", 2) )  
        {
        } else {
            file_name = dp->d_name;
            printf("file_name: \"%s\"\n",file_name);
        }
    }
    closedir(dir);
    return 0;
}



回答5:


int ret1, ret2;
char dev1[]  = { "ABC" };
char dev2[4] = { "ABC" };

dev2[3] = 'D';
ret1 = strncmp(dev1,dev2,strlen(dev1));  // # of characters
ret2 = strncmp(dev1,dev2,sizeof(dev1));  // # of characters plus '\0'

assume: dev1 is null terminated and dev2 is probably not. ret1 = 0 (false positive result), rather than ret2=-1 (valid result)

fazit: strncmp is not just a safer way for strcmp. depends on how you make use of it.

i´d use strcmp on strings, and strncmp on substring search.




回答6:


... under the same user scenario where whole strings need to be compared, ...

 strncmp(inputString, "LiternalString", strlen("LiternalString"));

Consider the case where string inputString is longer than the string literal.

const char *inputString = "LiternalString_XYZ";
int cmp = strncmp(inputString, "LiternalString", strlen("LiternalString"));
printf("%d\n", cmp); // prints 0.

But OP wanted whole strings compared.

const char *inputString = "LiternalString_XYZ";
int cmp = strcmp(inputString, "LiternalString");
printf("%d\n", cmp); // prints non-zero.

Conclusion to OP's direct question

I am wondering it makes sense or not.

No. To compare whole strings, strncmp() fails to consistently provide the correct result. Use strcmp().


Further

strncmp(s1,s2,n) can limit the search, so that it doesn't reach non-accessible memory if n was properly computed - which was not done in OP's code and problematic to do right when the best n is different for s1 and s2.

The size limit n applies to both s1 and s2 thus making this function useful for comparing prefixes, but not `"safer".

In OP's case, there is no reason to limit the search due to "safety" on account of the string length of the string literal as string literals always contains a terminating null character.

If anything, n should have been based on some property of inputString.

Code like strncmp(s1, string_literal, strlen(s1)) is functionally incorrect as the compare misses the null character. A wee bit better is strncmp(s1, string_literal, strlen(s1)+1), but that is functionally the same as the simpler strcmp(s1, string_literal) with no reduction in "safety".


The below offer some improve "safety" in case foo() did not properly form strings, but can provide the wrong answer if N != M as above.

char s1[N];
foo(s1); // populate s1 somehow
int cmp = strncmp(s1, string_literal, sizeof s1);

char s1[N];
char s2[M];
foo(s1); // populate s1 somehow
foo(s2); // populate s2 somehow
int cmp = strncmp(s1, s2, min(sizeof s1, sizeof s2));

Yet in those cases, the problem is in foo(), not here.
For me, if foo() was so questionable, I'd use the following

s1[sizeof s1 - 1] = '\0';
s2[sizeof s2 - 1] = '\0';
int cmp = strcmp(s1, s2);

or detect that foo() did not form a string.

char s1[N];
foo(s1);
if (memchr(s1, '\0', sizeof s1) == NULL) Oops();

Moral of the story: strncmp() is not a "safer" version of strcmp(). It is a tool for a different job: comparing string prefixes.




回答7:


strcmp could lead to storage volation and segmentation fault in case where one of arguments is not null-terminated string. Take a look why you should use strncpy instead of strcpy. Consequences are unlikely to happen in strcmp, but issue is the same. strnxxx function family try to prevent reading/writing not acquired memory.

Disadvantage of using strn is extra compare and decrement operation on counter.

In few words: strncmp is safer then strcmp, but it is slower too.




回答8:


I could see only one advantage, that strncmp will take slightly less time to execute than strcmp as we will always compare prefix of string to comapre rather than entire string.

I don't think that there is any security aspect involved in strcmp and strncmp algorithm. They are same except that in strncmp only first 'n' characters are compared.




回答9:


strncmp is more secure than strcmp

same as strncpy and strcpy or strlen and strnlen, because strcmp compares until first zeroterminator is found. strncmp compares until first zeroterminator but maximum n characters. So if your string has a defined length it is better to use the strn*-functions.

See also

http://www.cplusplus.com/reference/cstring/strncmp/?kw=strncmp



来源:https://stackoverflow.com/questions/30190460/advantages-of-strncmp-over-strcmp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!