问题
I made a function like this:
bool IsSameString(char* p1, char* p2)
{
return 0 == strcmp(p1, p2);
}
The problem is that sometimes, by mistake, arguments are passed which are not strings (meaning that p1
or p2
is not terminated with a null character).
Then, strcmp
continues comparing until it reaches non-accessible memory and crashes.
Is there a safe version of strcmp
? Or can I tell whether p1
(and p2
) is a string or not in a safe manner?
回答1:
No, there's no (standard) way to tell whether a char *
actually points to valid memory.
In your situation, it is better to use std::string
rather than char *
s for all your strings, along with the overloaded ==
operator. If you do this, the compiler would enforce type safety.
EDIT: As per the comments below if you find yourself in a situation where you sometimes pass char *
s that may or may not be valid strings to functions that expect null-terminated strings then something is fundamentally wrong with your approach, so basically
@janm's answer below.
回答2:
In some cases std::strncmp can solve your problem:
int strncmp ( const char * str1, const char * str2, size_t num );
It compares up to num characters of the C string str1 to those of the C string str2.
Also, take a look, what the US DHS National Cyber Security Division recommends on this matter:
Ensure that strings are null terminated before passing into strcmp. This can be enforced by always placing a \0 in the last allocated byte of the buffer.
char str1[] ="something";
char str2[] = "another thing";
/* In this case we know strings are null terminated. Pretend we don't. */
str1[sizeof(str1)-1] = '\0';
str2[sizeof(str2)-1] = '\0';
/* Now the following is safe. */
if (strcmp(str1, str2)) { /* do something */ } else { /* do something else */ }
回答3:
If you are passing strings to strcmp() that are not null terminated you have already lost. The fact that you have a string that is not null terminated (but should be) indicates that you have deeper issues in your code. You cannot change strcmp() to safely deal with this problem.
You should be writing your code so that can never happen. Start by using the string class. At the boundaries where you take data into your code you need to make sure you deal with the exceptional cases; if you get too much data you need to Do The Right Thing. That does not involve running off the end of your buffer. If you must perform I/O into a C style buffer, use functions where you specify the length of the buffer and detect and deal with cases where the buffer is not large enough at that point.
回答4:
There's no cure for this that is portable. The convention states that there's an extra character holding a null character that belongs to the same correctly allocated block of memory as the string itself. Either this convention is followed and everything's fine or undefined behaviour occurs.
If you know the length of the string you compare against you can use strncmp()
but his will not help if the string passed to your code is actually shorter than the string you compare against.
回答5:
you can use strncmp, But if possible use std::string to avoid many problems :)
回答6:
You can put an upper limit on the number of characters to be compared using the strncmp function.
回答7:
There is no best answer to this as you can't verify the char* is a string. The only solution is to create a type and use it for string for example str::string or create your own if you want something lighter. ie
struct MyString
{
MyString() : str(0), len(0) {}
MyString( char* x ) { len = strlen(x); str = strdup(x); }
⁓MyString() { if(str) free(str); }
char* str;
size_t len;
};
bool IsSameString(MyString& p1, MyString& p2)
{
return 0 == strcmp(p1.str, p2.str);
}
MyString str1("test");
MyString str2("test");
if( IsSameString( str1, str2 ) {}
回答8:
You dont write, what platform you are using. Windows has the following functions:
- IsBadStringPtr
- IsBadReadPtr
- IsBadWritePtr
IsBadStringPtr
might be what you are looking for, if you are using windows.
来源:https://stackoverflow.com/questions/1623769/is-there-any-safe-strcmp