Есть ли безопасный strcmp?

Я сделал такую функцию:

bool IsSameString(char* p1, char* p2) 
{
     return 0 == strcmp(p1, p2);
}

проблема в том, что иногда по ошибке передаются аргументы, которые не являются строками (это означает, что p1 или p2 не завершается нулевым символом). Затем:strcmp продолжает сравнение, пока не достигнет недоступной памяти и сбоев. Есть ли безопасная версия strcmp? Или я могу сказать,p1p2) является ли строка или нет безопасным способом?

8 ответов


нет ,нет (стандартного) способа узнать, является ли char * фактически указывает на действительную память.

в вашей ситуации, лучше использовать std::string, а не char *s для всех ваших строк вместе с перегруженным == оператора. Если вы это сделаете, компилятор будет обеспечивать безопасность типов.

EDIT: в соответствии с комментариями ниже, если вы окажетесь в ситуации, когда вы иногда проходите char *s, которые могут быть или не быть допустимыми строками для функций что ожидать нулевых строк, то что-то принципиально неправильно с вашим подходом, поэтому в основном ответы @janm ниже.


В некоторых случаях std::strncmp может решить вашу проблему:

int strncmp ( const char * str1, const char * str2, size_t num ); 

он сравнивает до num символов строки c str1 с символами строки c str2.


кроме того, посмотрите, что отдел национальной кибербезопасности DHS США рекомендует по этому вопросу:

убедитесь, что строки null завершены перед передачей в 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] = '';
str2[sizeof(str2)-1] = '';
/* Now the following is safe. */
if (strcmp(str1, str2)) { /* do something */ } else { /* do something else */ }

Если вы передаете strcmp() строки, которые не завершены null, вы уже потеряли. Тот факт, что у вас есть строка, которая не завершается null (но должна быть), указывает, что у вас есть более глубокие проблемы в коде. Вы не можете изменить strcmp (), чтобы безопасно справиться с этой проблемой.

вы должны писать свой код, чтобы этого никогда не произошло. Начните с использования класса String. На границах, где вы берете данные в свой код, вам нужно убедиться, что вы имеете дело с исключительные случаи; если вы получаете слишком много данных, вам нужно сделать правильную вещь. Это не включает в себя запуск конца буфера. Если необходимо выполнить ввод-вывод в буфер стиля C, используйте функции, в которых вы указываете длину буфера и обнаруживаете и обрабатываете случаи, когда буфер недостаточно велик в этот момент.


нет лекарства от этого, которое является портативным. Соглашение гласит, что есть дополнительный символ, содержащий нулевой символ, который принадлежит тому же правильно выделенному блоку памяти, что и сама строка. Либо это соглашение соблюдается, и все в порядке, либо происходит неопределенное поведение.

Если вы знаете длину строки, которую вы сравниваете, вы можете использовать strncmp() но его не поможет, если строка, переданная вашему коду, на самом деле короче строки, которую вы сравните против.


вы можете использовать strncmp, но по возможности используйте std:: string, чтобы избежать многих проблем:)


вы можете поставить верхний предел на количество символов для сравнения с помощью strncmp


вы не пишете, какую платформу вы используете. Windows имеет следующие функции:

IsBadStringPtr может быть то, что вы ищете, если вы используете Windows.


нет лучшего ответа на это, поскольку вы не можете проверить, что char* является строкой. Единственное решение-создать тип и использовать его для string, например 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 ) {}