Algoritma Copy-Paste Terbaik untuk C dan C ++. Koleksi Resep OS Haiku

Banyak kesalahan ketik dan kode Salin-Tempel menjadi topik untuk artikel tambahan tentang verifikasi kode Haiku oleh penganalisa PVS-Studio. Namun, akan ada kesalahan yang terkait bukan dengan kesalahan pengetikan, tetapi lebih karena kecerobohan dan refactoring yang gagal. Contoh kesalahan yang ditemukan menunjukkan seberapa kuat faktor manusia dalam pengembangan perangkat lunak.

Gambar 1

Pendahuluan


Haiku adalah sistem operasi open source gratis untuk komputer pribadi. Saat ini, sekelompok pengembang internasional sedang aktif mengerjakan komponen sistem. Dari perkembangan signifikan terakhir dalam pengembangan adalah porting LibreOffice ke sistem operasi dan rilis versi beta pertama dari R1 Beta 1.

Tim pengembang penganalisa kode statis PVS-Studio memantau pengembangan proyek sejak 2015, merilis ulasan tentang cacat kode. Ini adalah ulasan keempat sepanjang masa. Anda dapat berkenalan dengan artikel sebelumnya di tautan ini:

  1. Memeriksa sistem operasi Haiku (keluarga BeOS). Bagian 1
  2. Memeriksa sistem operasi Haiku (keluarga BeOS). Bagian 2 ;
  3. Cara menembak diri Anda di kaki di C dan C ++. Koleksi Resep OS Haiku

Fitur dari analisis kode terbaru adalah kemampuan untuk menggunakan versi resmi PVS-Studio untuk Linux. Pada 2015, itu tidak ada di sana, serta laporan yang nyaman untuk kesalahan tampilan. Sekarang kami akan mengirimkan laporan lengkap kepada pengembang dalam format yang nyaman.

Klasik genre


V501 Ada sub-ekspresi identik ke kiri dan ke kanan operator '-': (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; } 

Setiap programmer dalam hidupnya harus mencampur variabel a dan b , x dan y , i dan j ... dll.

V501 Ada sub-ekspresi identik ke kiri dan ke kanan '||' operator: input == __null || input == __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; } 

Dalam kondisi tersebut, pointer input yang sama diperiksa dua kali, dan pointer output tetap tidak dicentang, yang dapat menyebabkan dereferensi dari pointer nol.

Kode yang diperbaiki:

 if (input == NULL || output == NULL) return B_ERROR; 

V583 Operator '?:', Terlepas dari ekspresi kondisionalnya, selalu mengembalikan satu dan nilai yang sama: 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); .... } 

Operator ternary kehilangan artinya ketika programmer membuat kesalahan dan menulis dua nilai balik yang identik - 500000 .

V519 Variabel 'm_kindex1' diberi nilai dua kali berturut-turut. Mungkin ini sebuah kesalahan. Periksa baris: 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; } 

Terjadi kesalahan pada fungsi reset : kesalahan ketik dalam indeks m_kindex2 . Nilai variabel ini tidak akan diatur ulang, yang kemungkinan akan mempengaruhi eksekusi fragmen kode lainnya.

V501 Ada sub-ekspresi identik ke kiri dan ke kanan operator '>': 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]; .... } 

Di baris terakhir segera ada perbandingan variabel yang sama dan penugasan variabel yang sama. Saya tidak bisa berasumsi apa yang dipikirkan di sini. Tandai fragmen itu sebagai mencurigakan.

V570 Variabel 'wPipeIndex' ditugaskan untuk dirinya sendiri. CEchoGals_transport.cpp 244

 ECHOSTATUS CEchoGals::CloseAudio (....) { .... wPipeIndex = wPipeIndex; m_ProcessId[ wPipeIndex ] = NULL; m_Pipes[ wPipeIndex ].wInterleave = 0; .... } 

Variabel wPipeIndex diinisialisasi ke nilainya sendiri. Kemungkinan besar, kesalahan ketik dibuat.

Kesalahan dengan pointer


V522 Dereferencing dari pointer nol 'currentInterface' mungkin terjadi. Device.cpp 258

 Device::Device(....) : .... { .... usb_interface_info* currentInterface = NULL; // <= uint32 descriptorStart = sizeof(usb_configuration_descriptor); while (descriptorStart < actualLength) { switch (configData[descriptorStart + 1]) { .... case USB_DESCRIPTOR_ENDPOINT: { .... if (currentInterface == NULL) // <= break; currentInterface->endpoint_count++; .... } .... case USB_DESCRIPTOR_ENDPOINT_COMPANION: { usb_endpoint_descriptor* desc = currentInterface // <= ->endpoint[currentInterface->endpoint_count - 1].descr; .... } .... } 

Pointer currentInterface awalnya diinisialisasi ke nol dan kemudian diperiksa ketika memasuki cabang pernyataan switch , tetapi tidak dalam semua kasus. Penganalisa memperingatkan bahwa ketika pindah ke label USB_DESCRIPTOR_ENDPOINT_COMPANION , dimungkinkan untuk melakukan dereferensi pointer nol.

V522 Dereferencing 'direktori' penunjuk nol mungkin terjadi. PathMonitor.cpp 1465

 bool PathHandler::_EntryCreated(....) { .... Directory* directory = directoryNode->ToDirectory(); if (directory == NULL) { // We're out of sync with reality. if (!dryRun) { if (Entry* nodeEntry = directory->FirstNodeEntry()) { .... } } return false; } .... } 

Saya percaya bahwa ada kesalahan dalam membandingkan pointer direktori dengan nilai nol dan kondisinya harus sebaliknya. Dalam implementasi saat ini, jika variabel dryRun salah , maka pointer null direktori akan ditinjau ulang.

V522 Dereferencing dari 'input' pointer nol mungkin terjadi. MediaRecorder.cpp 343

 void GetInput(media_input* input); const media_input& BMediaRecorder::MediaInput() const { CALLED(); media_input* input = NULL; fNode->GetInput(input); return *input; } 

Input pointer diinisialisasi ke nol dan tetap pada nilai itu, karena dalam fungsi GetInput, pointer tidak berubah. Metode lain dari kelas BMediaRecorder menulis secara berbeda, misalnya:

 status_t BMediaRecorder::_Connect(....) { .... // Find our Node's free input media_input ourInput; fNode->GetInput(&ourInput); // <= .... } 

Semuanya benar di sini, tetapi tidak mungkin untuk menulis seperti ini di fragmen kode pertama, jika tidak fungsi akan mengembalikan tautan ke objek lokal, tetapi entah bagaimana kodenya perlu diperbaiki.

V522 Dereferencing dari null pointer 'mustFree' mungkin terjadi. RequestUnflattener.cpp 35

 status_t Reader::Read(int32 size, void** buffer, bool* mustFree) { if (size < 0 || !buffer || mustFree) // <= return B_BAD_VALUE; if (size == 0) { *buffer = NULL; *mustFree = false; // <= return B_OK; } .... } 

Dalam ekspresi bersyarat, di mana semua data input yang tidak valid diperiksa, kesalahan ketik dibuat ketika memeriksa pointer mustFree . Kemungkinan besar, jalan keluar dari fungsi harus bernilai nol pada pointer ini:

 if (size < 0 || !buffer || !mustFree) // <= return B_BAD_VALUE; 

V757 Ada kemungkinan bahwa variabel yang salah dibandingkan dengan nullptr setelah konversi jenis menggunakan 'dynamic_cast'. Periksa baris: 474, 476. recover.cpp 474

 void checkStructure(Disk &disk) { .... Inode* missing = gMissing.Get(run); dir = dynamic_cast<Directory *>(missing); if (missing == NULL) { .... } .... } 

Alih-alih penunjuk yang hilang , Anda harus memeriksa penunjuk dir setelah konversi jenis. Omong-omong, programmer C # sering membuat kesalahan yang sama. Ini sekali lagi membuktikan bahwa beberapa kesalahan tidak tergantung pada bahasa yang digunakan.

Beberapa tempat lebih mirip dalam kode:

  • V757 Ada kemungkinan bahwa variabel yang salah dibandingkan dengan nullptr setelah konversi jenis menggunakan 'dynamic_cast'. Periksa baris: 355, 357. ExpandoMenuBar.cpp 355
  • V757 Ada kemungkinan bahwa variabel yang salah dibandingkan dengan nullptr setelah konversi jenis menggunakan 'dynamic_cast'. Periksa baris: 600, 601. ValControl.cpp 600

Kesalahan Indeks


V557 Array overrun dimungkinkan. Indeks 'BT_SCO' menunjuk di luar batas array. h2upper.cpp 75

 struct bt_usb_dev { .... struct list nbuffersTx[(1 + 1 + 0 + 0)]; // <= [0..1] .... } typedef enum { BT_COMMAND = 0, BT_EVENT, BT_ACL, BT_SCO, // <= 3 BT_ESCO, HCI_NUM_PACKET_TYPES } bt_packet_t; void sched_tx_processing(bt_usb_dev* bdev) { .... if (!list_is_empty(&bdev->nbuffersTx[BT_SCO])) { // <= fail // TODO to be implemented } .... } 

Array bdev-> nbuffersTx hanya terdiri dari dua elemen, sedangkan dalam kode itu diakses oleh BT_SCO konstan, yang memiliki nilai 3. Terjadinya keluar yang dijamin melampaui batas-batas array terjadi.

V557 Array overrun dimungkinkan. Fungsi 'ieee80211_send_setup' memproses nilai '16'. Periksa argumen keempat. Periksa baris: 842, 911. ieee80211_output.c 842

 struct ieee80211_node { .... struct ieee80211_tx_ampdu ni_tx_ampdu[16]; // <= [0..15] .... }; #define IEEE80211_NONQOS_TID 16 int ieee80211_mgmt_output(....) { .... ieee80211_send_setup(ni, m, IEEE80211_FC0_TYPE_MGT | type, IEEE80211_NONQOS_TID, // <= 16 vap->iv_myaddr, ni->ni_macaddr, ni->ni_bssid); .... } void ieee80211_send_setup( struct ieee80211_node *ni, struct mbuf *m, int type, int tid, // <= 16 ....) { .... tap = &ni->ni_tx_ampdu[tid]; // <= 16 .... } 

Cara lain keluar dari array. Dalam hal ini, hanya satu item. Analisis antar prosedur membantu mengidentifikasi situasi di mana array ni-> ni_tx_ampdu , yang terdiri dari 16 elemen, diakses pada indeks 16 . Dalam C dan C ++, pengindeksan array dilakukan dari awal.

V781 Nilai dari variabel 'vektor' diperiksa setelah digunakan. Mungkin ada kesalahan dalam logika program. Periksa baris: 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); .... } 

Penganalisa mendeteksi panggilan ke array sc-> intrs pada indeks yang tidak valid (melampaui batas array). Alasan untuk ini adalah urutan kode yang salah. Di sini, array pertama kali diakses, dan kemudian dilakukan pemeriksaan untuk melihat apakah nilai indeks valid.

Seseorang mungkin berkata bahwa tidak akan ada masalah. Di sini, setelah semua, nilai elemen array tidak diambil, tetapi alamat sel diambil. Tidak, Anda tidak bisa melakukannya. Baca selengkapnya: " Mendereferensi pointer nol mengarah ke perilaku yang tidak terdefinisi ."

V519 Variabel ini diberi nilai dua kali berturut-turut. Mungkin ini sebuah kesalahan. Periksa baris: 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; } 

Elemen array dengan indeks NVME_INTEL_FEAT_MAX_LBA diberi nilai yang sama. Untungnya, semua konstanta yang mungkin terwakili dalam fungsi ini dan kode hanyalah hasil dari pemrograman Copy-Paste. Tetapi kemungkinan melakukan kesalahan dengan cara ini sangat tinggi.

V519 Variabel 'CopyPath [len]' diberi nilai dua kali berturut-turut. Mungkin ini sebuah kesalahan. Periksa baris: 92, 93. kernel_emu.cpp 93

 int UserlandFS::KernelEmu::new_path(const char *path, char **copy) { .... // append a dot, if desired if (appendDot) { copiedPath[len] = '.'; copiedPath[len] = '\0'; } .... } 

Dan di sini pengembang tidak beruntung dengan menyalin. Simbol "titik" ditambahkan ke garis tertentu dan segera ditimpa oleh terminal nol. Kemungkinan besar, pembuat kode menyalin string dan lupa untuk menambah indeks.

Kondisi aneh


V517 Penggunaan pola 'jika (A) {...} else jika (A) {...}' terdeteksi. Ada kemungkinan kehadiran kesalahan logis. Periksa baris: 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; } .... } 

Menyalin kode segera menyebabkan dua kesalahan. Ekspresi bersyarat identik. Kemungkinan besar, salah satunya harus memiliki perbandingan dengan string "false", bukan "true". Selanjutnya, di cabang yang memproses nilai "false", Anda harus mengubah nilai nilai dari 1 menjadi 0 . Algoritme mengasumsikan bahwa nilai-nilai lain selain benar atau salah akan dikonversi ke angka menggunakan fungsi atoi , tetapi karena kesalahan, teks juga akan mendapatkan teks "salah".

Ekspresi V547 'error == ((int) 0)' selalu benar. 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); } 

Analyzer mendeteksi bahwa nilai variabel kesalahan akan selalu menjadi B_OK . Kemungkinan besar, modifikasi variabel ini tidak terjawab dalam loop sementara .

V564 Operator '&' diterapkan pada nilai tipe bool. Anda mungkin lupa menyertakan tanda kurung atau bermaksud menggunakan operator '&&'. strtod.c 545

 static int lo0bits(ULong *y) { int k; ULong x = *y; .... if (!(x & 1)) { k++; x >>= 1; if (!x & 1) // <= return 32; } *y = x; return k; } 

Kemungkinan besar, dalam ekspresi bersyarat terakhir mereka lupa menempatkan tanda kurung, seperti pada kondisi di atas. Mungkin, operator negasi juga harus berada di luar tanda kurung:

 if (!(x & 1)) // <= return 32; 

V590 Pertimbangkan untuk memeriksa ungkapan ini. Ekspresi berlebihan atau mengandung kesalahan cetak. PoseView.cpp 5851

 bool BPoseView::AttributeChanged(const BMessage* message) { .... result = poseModel->OpenNode(); if (result == B_OK || result != B_BUSY) break; .... } 

Ini tidak jelas, tetapi hasil dari kondisi tidak bergantung pada nilai B_OK. Dengan demikian, dapat disederhanakan:

 If (result != B_BUSY) break; 

Ini dapat dengan mudah diverifikasi dengan membuat tabel kebenaran untuk nilai-nilai variabel hasil . Jika Anda perlu secara khusus mempertimbangkan nilai-nilai lain selain B_OK dan B_BUSY , maka kode harus ditulis ulang secara berbeda.

Dua kondisi yang serupa:

  • V590 Pertimbangkan untuk memeriksa ungkapan ini. Ekspresi berlebihan atau mengandung kesalahan cetak. Tracker.cpp 1714
  • V590 Pertimbangkan untuk memeriksa ungkapan ini. Ekspresi berlebihan atau mengandung kesalahan cetak. if_ipw.c 1871

V590 Pertimbangkan memeriksa 'argc == 0 || argc! = 2 ekspresi. Ekspresi berlebihan atau mengandung kesalahan cetak. cmds.c 2667

 void unsetoption(int argc, char *argv[]) { .... if (argc == 0 || argc != 2) { fprintf(ttyout, "usage: %s option\n", argv[0]); return; } .... } 

Mungkin ini adalah contoh paling sederhana yang menunjukkan operasi diagnostik V590 . Diperlukan untuk menampilkan deskripsi program jika tidak ada argumen yang lolos, atau tidak ada dua. Jelas, nilai apa pun selain dua, termasuk nol, tidak akan memenuhi kondisi tersebut. Oleh karena itu, kondisinya dapat dengan mudah disederhanakan sebagai berikut:

 if (argc != 2) { fprintf(ttyout, "usage: %s option\n", argv[0]); return; } 

V590 Pertimbangkan untuk memeriksa '* ptr =='; ' && * ptr! = '\ 0' 'ekspresi. Ekspresi berlebihan atau mengandung kesalahan cetak. 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); } .... } 

Dalam contoh ini, operator logis telah berubah, tetapi logikanya tetap sama. Di sini, kondisi loop sementara hanya bergantung pada apakah karakternya sama dengan SEMI_COLON atau tidak.

V590 Pertimbangkan untuk memeriksa ungkapan ini. Ekspresi berlebihan atau mengandung kesalahan cetak. 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; } .... } 

Sudah ada tiga kondisi dalam contoh ini. Ini juga dapat disederhanakan untuk memeriksa apakah pengguna telah memilih "ya" atau tidak:

 if (choice != "yes") { cerr << "MBR was NOT written" << endl; fs.close(); return B_ERROR; } 

Kesalahan lain-lain


V530 Nilai balik fungsi 'mulai' diperlukan untuk digunakan. 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(); // <= } } 

Penganalisa mendeteksi panggilan tidak berarti ke iterator begin (). Saya tidak dapat menebak bagaimana cara memperbaiki kode. Pengembang harus memperhatikan tempat ini.

V609 Bagilah dengan nol. Kisaran penyebut [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); // <= .... } 

Fungsi GetSIMDFormatByteSize sebenarnya mengembalikan 0 sebagai nilai default, yang berpotensi menyebabkan pembagian dengan nol.

V654 Kondisi 'specificSequence! = Sequence' dari loop selalu salah. 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; } 

Analisator benar bahwa kondisi pernyataan sementara selalu salah. Karena itu, tidak lebih dari satu iterasi dilakukan dalam satu lingkaran. Dengan kata lain, tidak ada yang akan berubah jika Anda menulis while (0) . Semua ini sangat aneh dan kode ini mengandung semacam kesalahan dalam logika kerja. Pengembang harus memperhatikan tempat ini.

V672 Mungkin tidak perlu membuat variabel 'path' baru di sini. Salah satu argumen fungsi memiliki nama yang sama dan argumen ini adalah referensi. Periksa baris: 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; } } .... } 

Variabel path diteruskan ke fungsi FindPath dengan referensi. Ini berarti bahwa dimungkinkan untuk memodifikasi variabel ini di tubuh fungsi. Tetapi di sini ada variabel lokal dengan nama yang sama yang sedang dimodifikasi. Dalam hal ini, semua perubahan hanya akan tetap dalam variabel lokal. Mungkin Anda harus mengganti nama atau menghapus variabel lokal.

V705 Ada kemungkinan bahwa blok 'lain' dilupakan atau dikomentari, sehingga mengubah logika operasi program. 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; } 

Contoh desain kode yang buruk. Kata kunci “beku” lain belum mengubah logika, tetapi ini sampai potongan kode pertama dimasukkan sebelum pernyataan pengembalian .

V763 Parameter 'menu' selalu ditulis ulang di badan fungsi sebelum digunakan. video.cpp 648

 bool video_mode_hook(Menu *menu, MenuItem *item) { video_mode *mode = NULL; menu = item->Submenu(); item = menu->FindMarked(); .... } 

Ada banyak kasus di mana argumen fungsi ditimpa segera di pintu masuk ke fungsi. Perilaku ini menyesatkan pengembang lain yang menjalankan fungsi yang sama ini.

Seluruh daftar tempat mencurigakan:

  • V763 Parameter 'force_16bit' selalu ditulis ulang di badan fungsi sebelum digunakan. ata_adapter.cpp 151
  • V763 Parameter 'force_16bit' selalu ditulis ulang di badan fungsi sebelum digunakan. ata_adapter.cpp 179
  • V763 Parameter 'menu' selalu ditulis ulang di badan fungsi sebelum digunakan. video.cpp 264
  • V763 Parameter 'panjang' selalu ditulis ulang di badan fungsi sebelum digunakan. MailMessage.cpp 677
  • V763 Parameter 'entri' selalu ditulis ulang di badan fungsi sebelum digunakan. IconCache.cpp 773
  • V763 Parameter 'entri' selalu ditulis ulang di badan fungsi sebelum digunakan. IconCache.cpp 832
  • V763 Parameter 'entri' selalu ditulis ulang di badan fungsi sebelum digunakan. IconCache.cpp 864
  • V763 Parameter 'rect' selalu ditulis ulang di badan fungsi sebelum digunakan. ErrorLogWindow.cpp 56
  • V763 Parameter 'updateRect' selalu ditulis ulang di badan fungsi sebelum digunakan. CalendarMenuWindow.cpp 49
  • V763 Parameter 'rect' selalu ditulis ulang di badan fungsi sebelum digunakan. MemoryView.cpp 165
  • V763 Parameter 'rect' selalu ditulis ulang di badan fungsi sebelum digunakan. TypeEditors.cpp 1124
  • V763 Parameter 'tinggi' selalu ditulis ulang di badan fungsi sebelum digunakan. Workspaces.cpp 857
  • V763 Parameter 'lebar' selalu ditulis ulang di badan fungsi sebelum digunakan. Workspaces.cpp 856
  • V763 Parameter 'bingkai' selalu ditulis ulang di badan fungsi sebelum digunakan. SwatchGroup.cpp 48
  • V763 Parameter 'bingkai' selalu ditulis ulang di badan fungsi sebelum digunakan. PlaylistWindow.cpp 89
  • V763 Parameter 'rect' selalu ditulis ulang di badan fungsi sebelum digunakan. ConfigView.cpp 78
  • V763 Parameter 'm' selalu ditulis ulang di badan fungsi sebelum digunakan. mkntfs.c 3917
  • V763 Parameter 'rxchainmask' selalu ditulis ulang di badan fungsi sebelum digunakan. ar5416_cal.c 463
  • V763 Parameter 'c' selalu ditulis ulang di badan fungsi sebelum digunakan. if_iwn.c 6854

Kesimpulan


Proyek Haiku adalah sumber bug yang menarik dan langka. Kami mengisi ulang database kami dari contoh kesalahan dan memperbaiki beberapa masalah dalam penganalisa yang diidentifikasi selama analisis kode.

Jika Anda belum memeriksa kode Anda dengan alat analisis kode apa pun untuk waktu yang lama, maka sesuatu yang dijelaskan mungkin juga ada dalam kode Anda. Gunakan PVS-Studio di proyek Anda untuk mengontrol kualitas kode jika ditulis dalam C, C ++, C # atau Java. Anda dapat mengunduh penganalisa tanpa registrasi dan SMS di sini .

Ingin mencoba Haiku dan memiliki pertanyaan? Pengembang Haiku mengundang Anda ke saluran telegram .



Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Svyatoslav Razmyslov. Algoritma Copy-Paste Terbaik untuk C dan C ++. Haiku OS Cookbook

Source: https://habr.com/ru/post/id461519/


All Articles