أصبحت العديد من الأخطاء المطبعية ورمز نسخ اللصق موضوعًا لمقال إضافي حول التحقق من كود هايكو بواسطة محلل PVS-Studio. ومع ذلك ، ستكون هناك أخطاء مرتبطة ليس كثيرا بالأخطاء المطبعية ، ولكن بالأخطاء والإهمال الناجح لإعادة البناء. توضح أمثلة الأخطاء التي تم العثور عليها مدى قوة العامل البشري في تطوير البرمجيات.
مقدمة
Haiku هو نظام تشغيل مجاني مفتوح المصدر لأجهزة الكمبيوتر الشخصية. حاليًا ، تعمل مجموعة دولية من المطورين بنشاط على مكونات النظام. من بين آخر التطورات الهامة في التطوير ، تم نقل LibreOffice إلى نظام التشغيل وإصدار أول إصدار تجريبي من R1 Beta 1.
يراقب فريق من مطوري محلل الكود الثابت في
PVS-Studio تطور المشروع منذ عام 2015 ، حيث يصدرون مراجعات عن عيوب الكود. هذا هو الاستعراض الرابع في كل العصور. يمكنك التعرف على المقالات السابقة على هذه الروابط:
- التحقق من نظام التشغيل هايكو (عائلة BeOS). الجزء 1
- التحقق من نظام التشغيل هايكو (عائلة BeOS). الجزء 2
- كيف تطلق النار على قدمك في C و C ++. Haiku OS وصفة مجموعة
تتمثل ميزة أحدث تحليل للكود في القدرة على استخدام الإصدار الرسمي من PVS-Studio لنظام التشغيل Linux. في عام 2015 ، لم يكن هناك ، وكذلك تقرير مناسب لعرض الأخطاء. الآن سوف نرسل للمطورين تقريرًا كاملاً بتنسيق مناسب.
كلاسيكيات هذا النوع
V501 هناك تعابير فرعية مماثلة إلى اليسار وإلى يمين عامل التشغيل '-': (addr_t) b - (addr_t) b BitmapManager.cpp 51
int compare_app_pointer(const ServerApp* a, const ServerApp* b) { return (addr_t)b - (addr_t)b; }
يجب على كل مبرمج في حياته مزج المتغيرات
a و
b و
x و
y و
i و
j ... إلخ.
V501 هناك تعبيرات فرعية مماثلة إلى اليسار وإلى يمين "||" عامل التشغيل: الإدخال == __null || إدخال == __null MediaClient.cpp 182
status_t BMediaClient::Unbind(BMediaInput* input, BMediaOutput* output) { CALLED(); if (input == NULL || input == NULL) return B_ERROR; if (input->fOwner != this || output->fOwner != this) return B_ERROR; input->fBind = NULL; output->fBind = NULL; return B_OK; }
في الحالة ، يتم فحص مؤشر
الإدخال نفسه مرتين ، ويظل مؤشر
الإخراج بدون تحديد ، مما قد يؤدي إلى إلغاء تحديد مؤشر القيمة الخالية.
كود مصحح:
if (input == NULL || output == NULL) return B_ERROR;
V583 يقوم
المشغل '؟:' ، بغض النظر عن تعبيره الشرطي ، دائمًا بإرجاع قيمة واحدة ونفس القيمة: 500000. usb_modeswitch.cpp 361
static status_t my_transfer_data(....) { .... do { bigtime_t timeout = directionIn ? 500000 : 500000; result = acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, timeout); .... } while (result == B_INTERRUPTED); .... }
فقد المشغل الثلاثي معناها عندما ارتكب المبرمج خطأ وكتب قيمتي عائد متطابقتين -
500000 .
V519 يتم تعيين قيم "m_kindex1" لقيمتين متتاليتين. ربما هذا خطأ. خطوط التحقق: 40 ، 41. agg_trans_double_path.cpp 41
trans_double_path::trans_double_path() : m_kindex1(0.0), m_kindex2(0.0), m_base_length(0.0), m_base_height(1.0), m_status1(initial), m_status2(initial), m_preserve_x_scale(true) { } void trans_double_path::reset() { m_src_vertices1.remove_all(); m_src_vertices2.remove_all(); m_kindex1 = 0.0; m_kindex1 = 0.0; m_status1 = initial; m_status2 = initial; }
حدث خطأ في وظيفة
إعادة الضبط : خطأ مطبعي في فهرس
m_kindex2 لن يتم إعادة تعيين قيمة هذا المتغير ، مما قد يؤثر على تنفيذ أجزاء التعليمات البرمجية الأخرى.
V501 هناك تعبيرات فرعية متطابقة إلى اليسار وإلى يمين عامل التشغيل '>': fg [order_type :: R]> fg [order_type :: R] agg_span_image_filter_rgba.h 898
typedef Source source_type; typedef typename source_type::color_type color_type; typedef typename source_type::order_type order_type; void generate(color_type* span, int x, int y, unsigned len) { .... if(fg[0] < 0) fg[0] = 0; if(fg[1] < 0) fg[1] = 0; if(fg[2] < 0) fg[2] = 0; if(fg[3] < 0) fg[3] = 0; if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; if(fg[order_type::R] > fg[order_type::R])fg[order_type::R] = fg[order_type::R]; if(fg[order_type::G] > fg[order_type::G])fg[order_type::G] = fg[order_type::G]; if(fg[order_type::B] > fg[order_type::B])fg[order_type::B] = fg[order_type::B]; .... }
في الأسطر الأخيرة ، هناك على الفور مقارنة بين نفس المتغيرات وتعيين نفس المتغيرات. لا أستطيع تحمل ما كان يعتقد هنا. فقط ضع علامة على الجزء المريب.
V570 يتم تعيين المتغير "wPipeIndex" لنفسه. CEchoGals_transport.cpp 244
ECHOSTATUS CEchoGals::CloseAudio (....) { .... wPipeIndex = wPipeIndex; m_ProcessId[ wPipeIndex ] = NULL; m_Pipes[ wPipeIndex ].wInterleave = 0; .... }
تتم تهيئة متغير
wPipeIndex إلى قيمته الخاصة. على الأرجح ، تم إجراء خطأ مطبعي.
أخطاء مع المؤشرات
V522 قد يتم إلغاء تأشير المؤشر الخالي "currentInterface". Device.cpp 258
Device::Device(....) : .... { .... usb_interface_info* currentInterface = NULL;
يتم تهيئة مؤشر
CurrentInterface في البداية إلى صفر ثم يتم التحقق منه عند إدخال فرع
بيان التبديل ، ولكن ليس في جميع الحالات. يحذر المحلل من أنه عند الانتقال إلى تسمية
USB_DESCRIPTOR_ENDPOINT_COMPANION ،
من الممكن
إلغاء تحديد مؤشر فارغ.
V522 قد يتم إلغاء تسجيل "دليل" المؤشر الخالي. PathMonitor.cpp 1465
bool PathHandler::_EntryCreated(....) { .... Directory* directory = directoryNode->ToDirectory(); if (directory == NULL) {
أعتقد أن هناك خطأ في مقارنة مؤشر
الدليل بقيمة فارغة ويجب أن يكون الشرط هو عكس ذلك. في التطبيق الحالي ، إذا كان المتغير
dryRun خطأ ، فسيتم إلغاء تحديد مؤشر
الدليل الخالي.
V522 قد يتم إلغاء إدخال مؤشر "الإدخال" الخالي من المؤشر. MediaRecorder.cpp 343
void GetInput(media_input* input); const media_input& BMediaRecorder::MediaInput() const { CALLED(); media_input* input = NULL; fNode->GetInput(input); return *input; }
تتم تهيئة مؤشر
الإدخال إلى صفر ويبقى عند هذه القيمة ، لأن في دالة GetInput ، لا يتغير المؤشر.
تكتب الطرق الأخرى لفئة
BMediaRecorder بشكل مختلف ، على سبيل المثال:
status_t BMediaRecorder::_Connect(....) { ....
كل شيء صحيح هنا ، لكن من المستحيل أن تكتب هكذا في الجزء الأول من الكود ، وإلا فإن الوظيفة ستعيد رابطًا للكائن المحلي ، لكن بطريقة ما يجب أن تكون الشفرة ثابتة.
V522 قد يتم إلغاء تسجيل المؤشر الخالي "mustFree". RequestUnflattener.cpp 35
status_t Reader::Read(int32 size, void** buffer, bool* mustFree) { if (size < 0 || !buffer || mustFree)
في التعبير الشرطي ، حيث يتم فحص جميع بيانات الإدخال غير الصالحة ، تم إجراء خطأ مطبعي عند التحقق من مؤشر
mustFree . على الأرجح ، يجب أن يكون الخروج من الوظيفة بقيمة صفر لهذا المؤشر:
if (size < 0 || !buffer || !mustFree)
V757 من الممكن مقارنة متغير غير صحيح مع nullptr بعد تحويل النوع باستخدام 'dynamic_cast'. خطوط التحقق: 474 ، 476. recovery.cpp 474
void checkStructure(Disk &disk) { .... Inode* missing = gMissing.Get(run); dir = dynamic_cast<Directory *>(missing); if (missing == NULL) { .... } .... }
بدلاً من المؤشر
المفقود ، يجب عليك التحقق من مؤشر
dir بعد تحويل النوع. بالمناسبة ،
غالبًا ما يرتكب مبرمجو C # خطأ مشابهًا. هذا يثبت مرة أخرى أن بعض الأخطاء مستقلة عن اللغة المستخدمة.
زوجان أكثر أماكن مماثلة في الرمز:
- V757 من الممكن مقارنة متغير غير صحيح مع nullptr بعد تحويل النوع باستخدام 'dynamic_cast'. خطوط التحقق: 355 ، 357. ExpandoMenuBar.cpp 355
- V757 من الممكن مقارنة متغير غير صحيح مع nullptr بعد تحويل النوع باستخدام 'dynamic_cast'. خطوط التحقق: 600 ، 601. ValControl.cpp 600
أخطاء الفهرس
V557 تجاوز الصفيف هو ممكن. يشير مؤشر 'BT_SCO' إلى ما وراء مجموعة الصفيف. h2upper.cpp 75
struct bt_usb_dev { .... struct list nbuffersTx[(1 + 1 + 0 + 0)];
يتكون
صفيف bdev-> nbuffersTx من عنصرين فقط ، بينما يتم الوصول إليه في الكود بواسطة BT_SCO الثابت ، والذي له قيمة 3. ويحدث خروج مضمون يتجاوز حدود المصفوفة.
V557 تجاوز الصفيف هو ممكن. تقوم دالة "ieee80211_send_setup" بمعالجة القيمة "16". تفقد الحجة الرابعة. خطوط التحقق: 842 ، 911. ieee80211_output.c 842
struct ieee80211_node { .... struct ieee80211_tx_ampdu ni_tx_ampdu[16];
طريقة أخرى للخروج من مجموعة. في هذه الحالة ، عنصر واحد فقط. ساعد التحليل Interprocedural في تحديد موقف حيث تم الوصول إلى الصفيف
ni-> ni_tx_ampdu ، الذي يتكون من 16 عنصرًا ، في الفهرس
16 . في C و C ++ ، تتم فهرسة الصفيف من البداية.
V781 يتم
التحقق من قيمة المتغير 'vector' بعد استخدامه. ربما هناك خطأ في منطق البرنامج. خطوط التحقق: 802 ، 805. oce_if.c 802
#define OCE_MAX_EQ 32 typedef struct oce_softc { .... OCE_INTR_INFO intrs[OCE_MAX_EQ]; .... } OCE_SOFTC, *POCE_SOFTC; static int oce_alloc_intr(POCE_SOFTC sc, int vector, void (*isr) (void *arg, int pending)) { POCE_INTR_INFO ii = &sc->intrs[vector]; int rc = 0, rr; if (vector >= OCE_MAX_EQ) return (EINVAL); .... }
اكتشف المحلل مكالمة إلى
مصفوفة sc-> intrs في فهرس غير صالح (يتجاوز حدود المصفوفة). السبب في ذلك هو ترتيب التعليمات البرمجية غير صحيح. هنا ، يتم الوصول إلى الصفيف لأول مرة ، ثم يتم إجراء التحقق لمعرفة ما إذا كانت قيمة الفهرس صالحة.
قد يقول شخص ما أنه لن تكون هناك مشكلة. هنا ، بعد كل شيء ، لا يتم استرداد قيمة عنصر الصفيف ، ولكن يتم ببساطة أخذ عنوان الخلية. لا ، لا يمكنك القيام بذلك على أي حال. اقرأ المزيد: "يؤدي
إلغاء مؤشر مؤشر فارغ إلى سلوك غير محدد ."
V519 يتم تخصيص القيم مرتين على التوالي. ربما هذا خطأ. خطوط التحقق: 199 ، 200. nvme_ctrlr.c 200
static void nvme_ctrlr_set_intel_supported_features(struct nvme_ctrlr *ctrlr) { bool *supported_feature = ctrlr->feature_supported; supported_feature[NVME_INTEL_FEAT_MAX_LBA] = true; supported_feature[NVME_INTEL_FEAT_MAX_LBA] = true; supported_feature[NVME_INTEL_FEAT_NATIVE_MAX_LBA] = true; supported_feature[NVME_INTEL_FEAT_POWER_GOVERNOR_SETTING] = true; supported_feature[NVME_INTEL_FEAT_SMBUS_ADDRESS] = true; supported_feature[NVME_INTEL_FEAT_LED_PATTERN] = true; supported_feature[NVME_INTEL_FEAT_RESET_TIMED_WORKLOAD_COUNTERS] = true; supported_feature[NVME_INTEL_FEAT_LATENCY_TRACKING] = true; }
يتم تعيين
عنصر الصفيف مع الفهرس
NVME_INTEL_FEAT_MAX_LBA بنفس القيمة. لحسن الحظ ، يتم تمثيل جميع الثوابت الممكنة في هذه الوظيفة ، والكود هو ببساطة نتيجة لبرمجة Copy-Paste. لكن احتمال ارتكاب الأخطاء بهذه الطريقة مرتفع للغاية.
V519 يتم تعيين متغير "copiedPath [len]" قيم مرتين على التوالي. ربما هذا خطأ. خطوط التحقق: 92 ، 93. kernel_emu.cpp 93
int UserlandFS::KernelEmu::new_path(const char *path, char **copy) { ....
وهنا المطور لم يحالفه الحظ في النسخ. تتم إضافة الرمز "dot" إلى سطر معين ويتم استبداله على الفور بواسطة نقطة الصفر. على الأرجح ، قام مؤلف الكود بنسخ السلسلة ونسي زيادة الفهرس.
ظروف غريبة
V517 استخدام
نمط "if (A) {...} آخر إذا تم اكتشاف (A) {...}". هناك احتمال لوجود خطأ منطقي. خطوط التحقق: 1407 ، 1410. FindPanel.cpp 1407
void FindPanel::BuildAttrQuery(BQuery* query, bool &dynamicDate) const { .... case B_BOOL_TYPE: { uint32 value; if (strcasecmp(textControl->Text(), "true") == 0) { value = 1; } else if (strcasecmp(textControl->Text(), "true") == 0) { value = 1; } else value = (uint32)atoi(textControl->Text()); value %= 2; query->PushUInt32(value); break; } .... }
نسخ الكود أدى على الفور إلى خطأين. التعبيرات الشرطية متطابقة. على الأرجح ، يجب أن يكون لدى أحدهم مقارنة بالسلسلة "false" ، بدلاً من "true". بعد ذلك ، في الفرع الذي يعالج القيمة "false" ، يجب عليك تغيير قيمة
القيمة من
1 إلى
0 . تفترض الخوارزمية أنه سيتم تحويل أي قيم أخرى غير
صحيحة أو
خاطئة إلى رقم باستخدام وظيفة
atoi ، ولكن بسبب الخطأ ، سيحصل النص أيضًا على النص "false".
تعبير
V547 'error == ((int) 0)' صحيح دائمًا. Directory.cpp 688
int32 BDirectory::CountEntries() { status_t error = Rewind(); if (error != B_OK) return error; int32 count = 0; BPrivate::Storage::LongDirEntry entry; while (error == B_OK) { if (GetNextDirents(&entry, sizeof(entry), 1) != 1) break; if (strcmp(entry.d_name, ".") != 0 && strcmp(entry.d_name, "..") != 0) count++; } Rewind(); return (error == B_OK ? count : error); }
اكتشف المحلل أن قيمة متغير
الخطأ ستكون دائمًا
B_OK . على الأرجح ، تم تفويت تعديل لهذا المتغير في
حلقة التكرار .
V564 يتم تطبيق عامل التشغيل "&" على قيمة نوع منطقي. ربما نسيت تضمين الأقواس أو المقصود استخدام عامل التشغيل "&&". strtod.c 545
static int lo0bits(ULong *y) { int k; ULong x = *y; .... if (!(x & 1)) { k++; x >>= 1; if (!x & 1)
على الأرجح ، في التعبير الشرطي الأخير نسوا وضع الأقواس ، كما في الشروط أعلاه. ربما ، هناك ، أيضًا ، يجب أن يكون عامل النفي خارج الأقواس:
if (!(x & 1))
V590 النظر في فحص هذا التعبير. التعبير مفرط أو يحتوي على خطأ مطبعي. PoseView.cpp 5851
bool BPoseView::AttributeChanged(const BMessage* message) { .... result = poseModel->OpenNode(); if (result == B_OK || result != B_BUSY) break; .... }
هذا غير واضح ، لكن نتيجة الشرط لا تعتمد على قيمة B_OK. وبالتالي ، يمكن تبسيطها:
If (result != B_BUSY) break;
يمكن التحقق من ذلك بسهولة عن طريق إنشاء جدول الحقيقة لقيم متغير
النتيجة . إذا كنت بحاجة إلى مراعاة القيم الأخرى بخلاف
B_OK و
B_BUSY ، فينبغي إعادة كتابة الرمز بطريقة مختلفة.
شرطين أكثر مماثلة:
- V590 النظر في فحص هذا التعبير. التعبير مفرط أو يحتوي على خطأ مطبعي. Tracker.cpp 1714
- V590 النظر في فحص هذا التعبير. التعبير مفرط أو يحتوي على خطأ مطبعي. if_ipw.c 1871
V590 خذ بعين الاعتبار فحص 'argc == 0 || argc! = 2 'تعبير. التعبير مفرط أو يحتوي على خطأ مطبعي. cmds.c 2667
void unsetoption(int argc, char *argv[]) { .... if (argc == 0 || argc != 2) { fprintf(ttyout, "usage: %s option\n", argv[0]); return; } .... }
ولعل هذا هو أبسط مثال يوضح عملية تشخيص
V590 . من الضروري عرض وصف البرنامج في حالة عدم وجود وسيطات تم تمريرها أو عدم وجود اثنتين منها. من الواضح أن أي قيم بخلاف القيمتين ، بما في ذلك الصفر ، لن تفي بالشرط. لذلك ، يمكن تبسيط الحالة بسهولة لما يلي:
if (argc != 2) { fprintf(ttyout, "usage: %s option\n", argv[0]); return; }
V590 خذ بعين الاعتبار فحص '* ptr =='؛ ' && * ptr! = '\ 0' 'التعبير. التعبير مفرط أو يحتوي على خطأ مطبعي. pc.c 316
ULONG parse_expression(char *str) { .... ptr = skipwhite(ptr); while (*ptr == SEMI_COLON && *ptr != '\0') { ptr++; if (*ptr == '\0') continue; val = assignment_expr(&ptr); } .... }
في هذا المثال ، تم تغيير العامل المنطقي ، لكن المنطق بقي كما هو. هنا ، لا تعتمد حالة حلقة التكرار إلا على ما إذا كانت الشخصية تساوي
SEMI_COLON أم لا.
V590 النظر في فحص هذا التعبير. التعبير مفرط أو يحتوي على خطأ مطبعي. writembr.cpp 99
int main(int argc, char** argv) { .... string choice; getline(cin, choice, '\n'); if (choice == "no" || choice == "" || choice != "yes") { cerr << "MBR was NOT written" << endl; fs.close(); return B_ERROR; } .... }
هناك بالفعل ثلاثة شروط في هذا المثال. يمكن تبسيطها أيضًا للتحقق مما إذا كان المستخدم قد اختار "نعم" أم لا:
if (choice != "yes") { cerr << "MBR was NOT written" << endl; fs.close(); return B_ERROR; }
أخطاء متنوعة
V530 يجب استخدام قيمة الإرجاع للدالة "start". IMAPFolder.cpp 414
void IMAPFolder::RegisterPendingBodies(...., const BMessenger* replyTo) { .... IMAP::MessageUIDList::const_iterator iterator = uids.begin(); for (; iterator != uids.end(); iterator++) { if (replyTo != NULL) fPendingBodies[*iterator].push_back(*replyTo); else fPendingBodies[*iterator].begin();
اكتشف المحلل مكالمة لا معنى لها
لبدء التكرار
(). لا يمكنني تخمين كيفية إصلاح الكود. يجب على المطور الانتباه إلى هذا المكان.
V609 قسّم على صفر. نطاق المقام [0..64]. UiUtils.cpp 544
static int32 GetSIMDFormatByteSize(uint32 format) { switch (format) { case SIMD_RENDER_FORMAT_INT8: return sizeof(char); case SIMD_RENDER_FORMAT_INT16: return sizeof(int16); case SIMD_RENDER_FORMAT_INT32: return sizeof(int32); case SIMD_RENDER_FORMAT_INT64: return sizeof(int64); case SIMD_RENDER_FORMAT_FLOAT: return sizeof(float); case SIMD_RENDER_FORMAT_DOUBLE: return sizeof(double); } return 0; } const BString& UiUtils::FormatSIMDValue(const BVariant& value, uint32 bitSize, uint32 format, BString& _output) { _output.SetTo("{"); char* data = (char*)value.ToPointer(); uint32 count = bitSize / (GetSIMDFormatByteSize(format) * 8);
ترجع الدالة
GetSIMDFormatByteSize فعليًا
0 كقيمة افتراضية ، مما قد يؤدي إلى القسمة على صفر.
V654 الشرط 'specificSequence! = Sequence' of loop is false دائماً. pthread_key.cpp 55
static void* get_key_value(pthread_thread* thread, uint32 key, int32 sequence) { pthread_key_data& keyData = thread->specific[key]; int32 specificSequence; void* value; do { specificSequence = keyData.sequence; if (specificSequence != sequence) return NULL; value = keyData.value; } while (specificSequence != sequence); keyData.value = NULL; return value; }
المحلل هو الصحيح أن حالة من
حين بيان دائما كاذبة. لهذا السبب ، لا يتم تنفيذ أكثر من تكرار واحد في حلقة. بمعنى آخر ، لن يتغير شيء إذا كتبت
(0) . كل هذا غريب للغاية ويحتوي هذا الكود على نوع من الخطأ في منطق العمل. يجب على المطورين الانتباه إلى هذا المكان.
V672 ربما لا توجد حاجة لإنشاء متغير "المسار" الجديد هنا. إحدى وسيطات الوظيفة لها نفس الاسم وهذه الوسيطة هي مرجع. خطوط التحقق: 348 ، 429. translate.cpp 429
status_t Translator::FindPath(...., TypeList &path, double &pathQuality) { .... TypeList path; double quality; if (FindPath(&formats[j], stream, typesSeen, path, quality) == B_OK) { if (bestQuality < quality * formatQuality) { bestQuality = quality * formatQuality; bestPath.SetTo(path); bestPath.Add(formats[j].type); status = B_OK; } } .... }
يتم تمرير متغير
المسار إلى وظيفة
FindPath حسب المرجع. هذا يعني أنه من الممكن تعديل هذا المتغير في نص الدالة. ولكن هنا يوجد متغير محلي بنفس الاسم الذي يتم تعديله. في هذه الحالة ، ستبقى جميع التغييرات فقط في المتغير المحلي. ربما يجب عليك إعادة تسمية أو حذف المتغير المحلي.
V705 من الممكن أن تكون كتلة "آخر" قد تم نسيانها أو التعليق عليها ، مما أدى إلى تغيير منطق عمليات البرنامج. HostnameView.cpp 109
status_t HostnameView::_LoadHostname() { BString fHostnameString; char hostname[MAXHOSTNAMELEN]; if (gethostname(hostname, MAXHOSTNAMELEN) == 0) { fHostnameString.SetTo(hostname, MAXHOSTNAMELEN); fHostname->SetText(fHostnameString); return B_OK; } else return B_ERROR; }
مثال على تصميم رمز الفقراء. لا تغير الكلمة الرئيسية "المجمدة" المنطق حتى الآن ، ولكن هذا حتى يتم إدخال الجزء الأول من الكود قبل
بيان الإرجاع .
تتم إعادة كتابة "قائمة" المعلمة
V763 دائمًا في
هيكل الوظيفة قبل استخدامها. video.cpp 648
bool video_mode_hook(Menu *menu, MenuItem *item) { video_mode *mode = NULL; menu = item->Submenu(); item = menu->FindMarked(); .... }
كانت هناك العديد من الحالات التي يتم فيها الكتابة على وسيطات الدالة فورًا عند مدخل الوظيفة. هذا السلوك مضلل للمطورين الآخرين الذين يقومون باستدعاء هذه الوظائف نفسها.
قائمة كاملة من الأماكن المشبوهة:
- تتم إعادة كتابة المعلمة V763 'force_16bit' دائمًا في نصوص الوظيفة قبل استخدامها. ata_adapter.cpp 151
- تتم إعادة كتابة المعلمة V763 'force_16bit' دائمًا في نصوص الوظيفة قبل استخدامها. ata_adapter.cpp 179
- تتم إعادة كتابة "قائمة" المعلمة V763 دائمًا في هيكل الوظيفة قبل استخدامها. video.cpp 264
- V763 يتم دائمًا إعادة كتابة المعلمة "الطول" في جسم الوظيفة قبل استخدامها. MailMessage.cpp 677
- تتم إعادة كتابة "إدخال" المعلمة V763 دائمًا في نصوص الوظيفة قبل استخدامها. IconCache.cpp 773
- تتم إعادة كتابة "إدخال" المعلمة V763 دائمًا في نصوص الوظيفة قبل استخدامها. IconCache.cpp 832
- تتم إعادة كتابة "إدخال" المعلمة V763 دائمًا في نصوص الوظيفة قبل استخدامها. IconCache.cpp 864
- تتم إعادة كتابة المعلمة V763 'rect' دائمًا في هيكل الوظيفة قبل استخدامها. ErrorLogWindow.cpp 56
- تتم إعادة كتابة المعلمة V763 "updateRect" دائمًا في هيكل الوظيفة قبل استخدامها. CalendarMenuWindow.cpp 49
- تتم إعادة كتابة المعلمة V763 'rect' دائمًا في هيكل الوظيفة قبل استخدامها. MemoryView.cpp 165
- تتم إعادة كتابة المعلمة V763 'rect' دائمًا في هيكل الوظيفة قبل استخدامها. TypeEditors.cpp 1124
- V763 يتم دائمًا إعادة كتابة المعلمة "الارتفاع" في جسم الوظيفة قبل استخدامها. Workspaces.cpp 857
- V763 يتم دائمًا إعادة كتابة المعلمة "عرض" في نصوص الوظيفة قبل استخدامها. Workspaces.cpp 856
- تتم إعادة كتابة "الإطار" للمعلمة V763 دائمًا في هيكل الوظيفة قبل استخدامه. SwatchGroup.cpp 48
- تتم إعادة كتابة "الإطار" للمعلمة V763 دائمًا في هيكل الوظيفة قبل استخدامه. PlaylistWindow.cpp 89
- تتم إعادة كتابة المعلمة V763 'rect' دائمًا في هيكل الوظيفة قبل استخدامها. ConfigView.cpp 78
- تتم إعادة كتابة المعلمة V763 دائمًا في جسم الوظيفة قبل استخدامها. mkntfs.c 3917
- تتم إعادة كتابة المعلمة V763 "rxchainmask" دائمًا في هيكل الوظيفة قبل استخدامها. ar5416_cal.c 463
- تتم إعادة كتابة المعلمة V763 دائمًا في جسم الوظيفة قبل استخدامها. if_iwn.c 6854
استنتاج
مشروع هايكو هو مصدر البق مثيرة للاهتمام ونادرة. لقد قمنا بتجديد قاعدة بياناتنا لأمثلة عن الأخطاء وحلنا العديد من المشكلات في المحلل المحدد خلال تحليل الكود.
إذا لم تقم بفحص الكود الخاص بك باستخدام أي من أدوات تحليل الشفرة لفترة طويلة ، فمن المحتمل أن يكون هناك شيء ما هو موضح في الكود أيضًا. استخدم PVS-Studio في مشروعك للتحكم في جودة الشفرة إذا كانت مكتوبة بلغات C أو C ++ أو C # أو Java. يمكنك تنزيل المحلل دون تسجيل ورسالة نصية قصيرة
هنا .
تريد أن تجرب هايكو ولديك أي أسئلة؟ يدعوك مطورو Haiku إلى
قناة التلغراف .

إذا كنت ترغب في مشاركة هذه المقالة مع جمهور يتحدث الإنجليزية ، فالرجاء استخدام الرابط الخاص بالترجمة: Svyatoslav Razmyslov.
أفضل خوارزميات نسخ ولصق لـ C و C ++. هايكو OS كتاب الطبخ