سؤال

لقد قمت بعمل وظيفة مثل هذا:

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

المشكلة هي أنه في بعض الأحيان، عن طريق الخطأ، يتم تمرير وسيطات ليست سلاسل (بمعنى ذلك p1 أو p2 لم يتم إنهاؤه بحرف فارغ).ثم، strcmp يستمر في المقارنة حتى يصل إلى الذاكرة التي لا يمكن الوصول إليها ويتعطل.هل هناك نسخة آمنة من strcmp؟أو هل يمكنني معرفة ما إذا كان p1p2) هل هي سلسلة أم لا بطريقة آمنة؟

هل كانت مفيدة؟

المحلول

لا، لا توجد طريقة (قياسية) لمعرفة ما إذا كان أ char * يشير في الواقع إلى ذاكرة صالحة.

في حالتك، فمن الأفضل أن تستخدم std::string بدلا من char *s لجميع سلاسلك، إلى جانب التحميل الزائد == المشغل أو العامل.إذا قمت بذلك، فإن المترجم سيفرض سلامة النوع.

يحرر: وفقًا للتعليقات أدناه، إذا وجدت نفسك في موقف تمر فيه أحيانًا char *S التي قد تكون أو لا تكون سلاسل صالحة للوظائف التي تتوقع سلاسل منتهية خالية ، فإن هناك خطأ ما في نهجك ، لذلك في الأساس @إجابة Janm أدناه.

نصائح أخرى

في بعض الحالات std::strncmp يمكن أن تحل مشكلتك:

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

وويقارن ما يصل إلى أحرف الأسطوانات من str1 C سلسلة لتلك التي str2 C سلسلة.


وبالإضافة إلى ذلك، إلقاء نظرة، ما شعبة الأمن القومي سايبر DHS الولايات المتحدة <لأ href = "https://buildsecurityin.us-cert.gov/daisy/bsi-rules/home/g1/847-BSI.html" يختلط = "noreferrer"> يوصي على هذه المسألة:

<اقتباس فقرة>   

وتأكد أن سلاسل يتم إنهاء اغية قبل تمرير إلى 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 */ }

إذا كنت تمر السلاسل إلى strcmp () التي ليست فارغة إنهاء كنت قد فقدت بالفعل. حقيقة أن لديك سلسلة غير منتهية (ولكن ينبغي أن يكون) يشير إلى أن لديك مشاكل أعمق في التعليمات البرمجية. لا يمكنك تغيير strcmp () للتعامل بأمان مع هذه المشكلة.

ويجب أن تكون كتابة التعليمات البرمجية بحيث لا يمكن أبدا أن يحدث. بدء باستخدام فئة السلسلة. في حدود حيث أن تأخذ بيانات في التعليمات البرمجية التي تحتاج إليها للتأكد من التعامل مع الحالات الاستثنائية. اذا كان لديك الكثير من البيانات التي تحتاج إليها لفعل الشيء الصحيح. التي لا تنطوي على يلوذ بالفرار بعد نهاية المخزن المؤقت الخاص بك. إذا كان يجب إجراء I / O في المخزن مؤقت C النمط، واستخدام وظائف حيث يمكنك تحديد طول المخزن المؤقت وكشف والتعامل مع الحالات التي تكون فيها عازلة ليست كبيرة بما فيه الكفاية في هذه النقطة.

وليس هناك علاج لهذا أن هو محمول. وتنص الاتفاقية على أن هناك الزائدة عقد حرف فارغة الذي ينتمي إلى نفس الكتلة المخصصة بشكل صحيح من الذاكرة والسلسلة نفسها. إما ويتبع هذه الاتفاقية ويحدث سلوك كل شيء على ما يرام أو غير معرف.

إذا كنت تعرف طول السلسلة قارنت ضد يمكنك استخدام strncmp() ولكن له لا يساعد إذا كانت السلسلة التي تم تمريرها إلى التعليمات البرمجية أقصر في الواقع من سلسلة قارنت ضد.

ويمكنك استخدام strncmp، ولكن إذا كان ذلك ممكنا الأمراض المنقولة جنسيا استخدام :: سلسلة لتجنب العديد من المشاكل :)

ويمكنك وضع حد أقصى لعدد الأحرف يمكن مقارنتها باستخدام strncmp وظيفة.

وليس هناك أفضل رد على هذا النحو الذي لا يمكن التحقق من شار * غير سلسلة. الحل الوحيد هو خلق نوع واستخدامه لسلسلة على سبيل المثال شارع :: سلسلة أو إنشاء الخاصة بك إذا كنت تريد شيئا أخف وزنا. أي

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 ) {}

أنت لا تكتب، ما هي المنصة التي تستخدمها.يحتوي Windows على الوظائف التالية:

IsBadStringPtr قد يكون هذا هو ما تبحث عنه، إذا كنت تستخدم windows.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top