Есть ли безопасный strcmp?
Я сделал такую функцию:
bool IsSameString(char* p1, char* p2)
{
return 0 == strcmp(p1, p2);
}
Проблема заключается в том, что иногда, по ошибке, передаются аргументы, которые не являются строками (это означает, что p1
или p2
не заканчивается нулевым символом).
Затем strcmp
продолжает сравнивать, пока не достигнет недоступной памяти и сработает.
Есть ли безопасная версия strcmp
? Или я могу сказать, является ли p1
(и p2
) строкой или нет в безопасном режиме?
Ответы
Ответ 1
Нет, нет (стандартного) способа определить, действительно ли char *
указывает на действительную память.
В вашей ситуации лучше использовать std::string
вместо char *
для всех ваших строк вместе с перегруженным оператором ==
. Если вы это сделаете, компилятор обеспечит безопасность типов.
РЕДАКТИРОВАТЬ: В соответствии с приведенными ниже комментариями, если вы оказываетесь в ситуации, когда вы иногда проходите char *
, которые могут или не могут быть действительными строками для функций, которые ожидают строки с нулевым завершением, тогда что-то есть в корне неправильно с вашим подходом, поэтому в основном
@janm ответьте ниже.
Ответ 2
В некоторых случаях std::strncmp
может решить вашу проблему:
int strncmp ( const char * str1, const char * str2, size_t num );
Он сравнивает до num символов строки C str1 с символами строки C str2.
Кроме того, посмотрите, что US DHS National Cyber Security Division рекомендует по этому вопросу:
Убедитесь, что строки переданы в нуль до перехода в strcmp. Это может быть принудительно, всегда помещая \0 в последний выделенный байт буфера.
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
Если вы передаете строки strcmp(), которые не завершены нулем, вы уже потеряли. Тот факт, что у вас есть строка, которая не завершена нулем (но должна быть), указывает на то, что у вас есть более глубокие проблемы в вашем коде. Вы не можете изменить strcmp(), чтобы безопасно справиться с этой проблемой.
Вы должны писать свой код, чтобы этого никогда не было. Начните с использования класса string. На границах, где вы берете данные в свой код, вы должны убедиться, что имеете дело с исключительными случаями; если вы получаете слишком много данных, вам нужно сделать правильную вещь. Это не связано с запуском конца вашего буфера. Если вы должны выполнять ввод-вывод в буфере стиля C, используйте функции, в которых вы указываете длину буфера, и обнаруживаете и обрабатываете случаи, когда буфер недостаточно велик в этой точке.
Ответ 4
Там нет лекарств, которые переносятся. В соглашении говорится, что дополнительный символ содержит нулевой символ, принадлежащий тому же правильно выделенному блоку памяти, что и сама строка. Выполняется либо это соглашение, и все мелкие или undefined поведение.
Если вы знаете длину строки, которую вы сравниваете, вы можете использовать strncmp()
, но его не поможет, если строка, переданная вашему коду, на самом деле короче строки, которую вы сравниваете.
Ответ 5
вы можете использовать strncmp, но если возможно, используйте std::string, чтобы избежать многих проблем:)
Ответ 6
Вы можете установить верхний предел количества сопоставляемых символов, используя функцию strncmp.
Ответ 7
Вы не пишете, какую платформу вы используете. Windows выполняет следующие функции:
IsBadStringPtr
может быть тем, что вы ищете, если вы используете окна.
Ответ 8
Нет лучшего ответа на этот вопрос, поскольку вы не можете проверить, что char * - это строка. Единственное решение - создать тип и использовать его для строки, например str:: string, или создать свой собственный, если вы хотите что-то более легкое. то есть
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 ) {}