14

私はこのような関数を作りました:

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

問題は、誤って文字列ではない引数が渡される場合があることです (つまり、p1orp2がヌル文字で終了していないことを意味します)。その後、strcmpアクセスできないメモリに到達してクラッシュするまで比較を続けます。の安全なバージョンはありstrcmpますか? または、安全な方法でp1(and ) が文字列かどうかを判断できますか?p2

4

8 に答える 8

21

いいえ、 achar *が実際に有効なメモリを指しているかどうかを判断する (標準的な) 方法はありません。

あなたの状況では、オーバーロードされた演算子とともに、すべての文字列に対して sstd::stringではなく使用することをお勧めします。これを行うと、コンパイラはタイプ セーフを適用します。char *==

編集:以下のコメントのように、有効な文字列である場合とそうでない場合がある s を、null で終わる文字列を期待する関数に渡すことがあるchar *場合は、アプローチに根本的な問題があるため、基本的に @janm の回答を以下に示します。 .

于 2009-10-26T09:06:46.513 に答える
18

場合によってstd::strncmpは、問題を解決できます。

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

C 文字列 str1 の最大 num 文字を C 文字列 str2 の文字と比較します。


また、この問題に関して米国 DHS の国家サイバー セキュリティ部門が推奨していることもご覧ください。

strcmp に渡す前に、文字列が null で終了していることを確認してください。これは、バッファの最後に割り当てられたバイトに常に \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 */ }
于 2009-10-26T09:05:11.223 に答える
14

null で終了していない文字列を strcmp() に渡している場合は、すでに失われています。null で終了していない (ただし終了する必要がある) 文字列があるという事実は、コードに深刻な問題があることを示しています。この問題に安全に対処するために strcmp() を変更することはできません。

決して起こらないようにコードを書く必要があります。文字列クラスを使用して開始します。コードにデータを取り込む境界では、例外的なケースに確実に対処する必要があります。データが多すぎる場合は、正しいことを行う必要があります。これには、バッファの最後から実行する必要はありません。C スタイルのバッファーへの I/O を実行する必要がある場合は、バッファーの長さを指定する関数を使用し、その時点でバッファーが十分に大きくない場合を検出して対処します。

于 2009-10-26T11:19:39.797 に答える
7

移植可能なこれに対する治療法はありません。規則では、文字列自体と同じように正しく割り当てられたメモリ ブロックに属する null 文字を保持する余分な文字があると述べています。この規則に従っていると、すべてが正常に動作するか、未定義の動作が発生します。

比較する文字列の長さがわかっている場合は使用できますstrncmp()が、コードに渡された文字列が実際に比較する文字列よりも短い場合は役に立ちません。

于 2009-10-26T09:04:38.773 に答える
3

strncmp を使用できますが、可能であれば std::string を使用して多くの問題を回避してください :)

于 2009-10-26T09:07:02.250 に答える
1

strncmp関数 を使用すると、比較する文字数に上限を設けることができます。

于 2009-10-26T09:06:22.763 に答える
-1

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 ) {}
于 2009-10-26T11:08:12.590 に答える
-2

使用しているプラ​​ットフォームを書きません。Windows には次の機能があります。

IsBadStringPtrWindowsを使用している場合は、探しているものかもしれません。

于 2009-10-26T10:57:21.023 に答える