سؤال

تحرير: لقد أضفت المصدر للمثال.

جئت عبر هذا المثال:

char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;

/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);

/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );

التي أنتجت هذا الناتج:

الوجهة هي الأصل = 'ABCDEFG' بعد strcpy، تصبح الوجهة "123456789" الوجهة 1 هي في الأصل = "ABCDEFG" بعد strncpy، يصبح الوجهة 1 '12345fg'

مما يجعلني أتساءل لماذا يريد أي شخص هذا التأثير. يبدو أنه سيكون مربكا. هذا البرنامج يجعلني أعتقد أنك تستطيع نسخ اسم شخص ما (على سبيل المثال. توم بروكاو) مع توم bro763.

ما هي مزايا استخدام strncpy() على strcpy()?

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

المحلول

strncpy يحمل الفضاد المخزن المؤقت عن طريق طلبك لوضع طول فيه. strcpy يعتمد على زائدة \0, ، والتي قد لا تحدث دائما.

ثانيا، لماذا اخترت فقط نسخ 5 أحرف على 7 سلسلة أحرف خارجي، لكنها تنتج السلوك المتوقع. انها مجرد نسخ فوق الأول n الشخصيات، حيث n هي الحجة الثالثة.

ال n تستخدم جميع الوظائف كترميز دفاعي ضد الفائض المخزن المؤقت. يرجى استخدامها بدلا من الوظائف القديمة، مثل strcpy.

نصائح أخرى

ال strncpy() تم تصميم الدالة بمشكلة خاصة جدا في الاعتبار: معالجة السلاسل المخزنة في طريقة إدخالات دليل UNIX الأصلية. استخدمت هذه صفيف بحجم ثابت، وتم استخدام منفذ المنهي فقط إذا كان اسم الملف أقصر من الصفيف.

هذا ما وراء الشذوذين strncpy():

  • لا يضع المنحظر في الوجهة إذا كانت مليئة تماما؛ و
  • انها دائما تملأ الوجهة تماما، مع nuls إذا لزم الأمر.

ل "أكثر أمانا strcpy()"أنت أفضل حالا باستخدام strncat() مثل ذلك:

if (dest_size > 0)
{
    dest[0] = '\0';
    strncat(dest, source, dest_size - 1);
}

من شأنها أن تنتهي دائما النتيجة، ولن نسخ أكثر من اللازم.

بينما أعرف النية وراء strncpy, ، ليست حقا وظيفة جيدة حقا. تجنب كليهما. يشرح ريموند تشن.

شخصيا، استنتاجي هو ببساطة تجنب strncpy وجميع أصدقائها إذا كنت تتعامل مع سلاسل غير ذات النهاية. على الرغم من "Str" في الاسم، فإن هذه الوظائف لا تنتج سلاسل غير ذات النهاية. يقومون بتحويل سلسلة ذات شهرين إلى مخزن مؤقت في الطابع الخام. استخدامها حيث من المتوقع أن تكون السلسلة التي تم إنهاءها بوضوح مثل العازلة الثانية خطأ عادي. لا تفشل فقط في الحصول على إنهاء NULL المناسب إذا كان المصدر طويلا جدا، ولكن إذا كان المصدر قصيرا، فستحصل على الحشو غير الضروري.

أنظر أيضا لماذا غير آمن strncpy؟

strncpy ليس أكثر أمانا من strcpy، فإنه يتداول فقط نوع واحد من الأخطاء مع آخر. في ج، عند التعامل مع سلاسل ج، تحتاج إلى معرفة حجم المخازن المؤقتة الخاصة بك، لا توجد وسيلة حولها. تم تبرير STRNCPY لهذا الدليل الذي ذكره الآخرون، ولكن خلاف ذلك، يجب ألا تستخدمه أبدا:

  • إذا كنت تعرف طول السلسلة والمخزن المؤقت، فلماذا استخدام StrNCPY؟ إنه مضيعة لحساب القوة في أفضل الأحوال (إضافة عديمة الفائدة 0)
  • إذا كنت لا تعرف الأطوال، فأنت تخاطر باستقرار بخطواتك، وهي ليست أفضل بكثير من تجاوز تجاوز المخزن المؤقت

ما كنت تبحث عن هو وظيفة strlcpy() الذي ينتهي دائما السلسلة مع 0 وتهيئة المخزن المؤقت. كما أنه قادر على اكتشاف الفائض. المشكلة الوحيدة، إنها ليست (حقا) محمولة موجودة فقط على بعض الأنظمة (BSD، Solaris). المشكلة في هذه الوظيفة هي أنه يفتح علبة أخرى من الديدان كما يمكن أن ينظر إليها من قبل المناقشاتhttp://en.wikipedia.org/wiki/stlcpy.

رأيي الشخصي هو أنه أكثر فائدة بشكل كبير من strncpy() و strcpy(). وبعد لديها أداء أفضل وهو رفيق جيد snprintf(). وبعد بالنسبة إلى المنصات التي لا تملكها، فمن السهل نسبيا التنفيذ. (لمرحلة التطورات من تطبيق أبدوها هذين الوظيفة (snprintf() و strlcpy()) مع إصدار الملاءمة الذي يجذب بوحشية البرنامج على الفائض أو اقتطاع المخزن المؤقت. هذا يسمح للقبض بسرعة أسوأ الجناة. خاصة إذا كنت تعمل على CodeBase من شخص آخر.

تعديل: strlcpy() يمكن تنفيذها بسهولة:

size_t strlcpy(char *dst, const char *src, size_t dstsize)
{
  size_t len = strlen(src);
  if(dstsize) {
    size_t bl = (len < dstsize-1 ? len : dstsize-1);
    ((char*)memcpy(dst, src, bl))[bl] = 0;
  }
  return len;
}

ال strncpy() وظيفة أكثر أمانا: عليك أن تمر الحد الأقصى للطول الذي يمكن أن يقبله المخزن المؤقت الوجهة. وإلا فقد يحدث أن السلسلة المصدر ليست بشكل صحيح تم إنهاء 0، وفي هذه الحالة strcpy() يمكن أن تكتب الدالة المزيد من الأحرف إلى الوجهة، أو تفسير أي شيء في الذاكرة بعد المخزن المؤقت الوجهة. هذه هي مشكلة تجاوز المخزن المؤقت المستخدمة في العديد من الاستغلال

أيضا لوظائف POSIX API مثل read() الذي لا يضع إنهاء 0 في المخزن المؤقت، ولكن إرجاع عدد بايت القراءة، ستفعل يدويا 0، أو نسخه باستخدام strncpy().

في رمز المثال الخاص بك، index في الواقع ليس مؤشرا، ولكن count - يخبر عدد الأحرف في الغالب لنسخ من مصدر إلى وجهة. إذا لم يكن هناك بايت فارغة بين أول بايت من المصدر، فلن يتم إنهاء السلسلة الموضوعة في الوجهة NULL

strncpy يملأ الوجهة حتى مع " 0" لحجم المصدر، EventHough حجم الوجهة أصغر ....

manpage:

إذا كان طول SRC أقل من N، STRNCPY () منصات الفترة المتبقية مع البايت البايت.

وليس فقط الباقي ... أيضا بعد هذا حتى يتم الوصول إلى أحرف N. وبالتالي تحصل على تجاوز ... (انظر تنفيذ صفحة الرجل)

يمكن استخدام هذا في العديد من السيناريوهات الأخرى، حيث تحتاج إلى نسخ جزء فقط من السلسلة الأصلية إلى الوجهة. باستخدام STRNCPY () يمكنك نسخ جزء محدود من السلسلة الأصلية بدلا من strcpy (). أرى الرمز الذي طرحته يأتي من publib.boulder.ibm.com..

هذا يعتمد على شرطنا. لمستخدمي ويندوز

نستخدم STRNCPY كلما كنا لا نريد نسخ السلسلة بأكملها أو نريد نسخ عدد n فقط من الأحرف. لكن Strcpy نسخ السلسلة بأكملها بما في ذلك إنهاء حرف فارغ.

ستساعدك هذه الروابط أكثر لمعرفة STRCPY و STRNCPY وأين يمكننا استخدامها.

حول strcpy.

حول strncpy.

STRNCPY هو إصدار أكثر أمانا من strcpy كمسألة فعالة يجب ألا تستخدم strcpy أبدا لأن مشكلة عدم حصانة الفائض المحتملة التي تجعلك نظام عرضة لجميع الهجمات

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