Banyak kesalahan ketik dan kode Salin-Tempel menjadi topik utama artikel tambahan tentang memeriksa kode Haiku oleh penganalisa PVS-Studio. Namun artikel ini sebagian besar menceritakan tentang kesalahan yang berkaitan dengan kesembronoan dan kegagalan refactoring, daripada kesalahan ketik. Kesalahan yang ditemukan menunjukkan seberapa kuat faktor manusia dalam pengembangan perangkat lunak.
Pendahuluan
Haiku adalah sistem operasi open source gratis untuk komputer pribadi. Tim pengembangan internasional saat ini sedang mengerjakan komponen-komponen sistem. Porting Libre Office di OS dan rilis R1 Beta 1 pertama menonjol di antara peningkatan pengembangan signifikan baru-baru ini.
Tim pengembang dari
PVS-Studio mengikuti pengembangan proyek ini sejak 2015 dan memposting ulasan tentang kerusakan kode. Ini adalah ulasan keempat sepanjang masa. Anda dapat membaca artikel sebelumnya dengan tautan ini:
- Analisis Sistem Operasi Haiku (BeOS Family), oleh PVS-Studio, Bagian 1 ;
- Analisis Sistem Operasi Haiku (BeOS Family) oleh PVS-Studio. Bagian 2 ;
- Cara menembak diri Anda di kaki di C dan C ++. Buku masak Haiku OS
Fitur dari analisis kode terakhir adalah kemampuan untuk menggunakan versi resmi PVS-Studio untuk Linux. Baik PVS-Studio untuk Linux, maupun laporan yang nyaman untuk melihat kesalahan tidak tersedia pada tahun 2015. Kali ini kami akan mengirimkan laporan lengkap dalam format yang mudah ke pengembang Haiku.
Klasik
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 pengembang harus mencampur variabel
a dan
b ,
x dan
y ,
i dan
j ... setidaknya sekali dalam hidupnya.
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; }
Input pointer yang sama diperiksa dalam kondisi dua kali. Sedangkan pointer
output tetap tidak dicentang, yang dapat menyebabkan dereferensi pointer nol.
Kode tetap:
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 menjadi sia-sia, ketika pembuat kode melakukan 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; }
Ada kesalahan dalam fungsi
reset : kesalahan ketik dalam indeks variabel
m_kindex2 . Variabel ini tidak akan direset, yang mungkin 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, ada dua masalah sekaligus: perbandingan dan penugasan variabel yang sama. Saya bahkan tidak bisa menyarankan apa gagasan penulis itu. Saya hanya akan melihat cuplikan ini 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 dengan 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;
Pointer
currentInterface awalnya diinisialisasi dengan nol dan kemudian diperiksa ketika masuk dalam cabang-cabang operator
switch , tetapi tidak dalam semua kasus. Penganalisa memperingatkan bahwa ketika melompat ke label kasus
USB_DESCRIPTOR_ENDPOINT_COMPANION , dereference pointer nol mungkin terjadi.
V522 Dereferencing 'direktori' penunjuk nol mungkin terjadi. PathMonitor.cpp 1465
bool PathHandler::_EntryCreated(....) { .... Directory* directory = directoryNode->ToDirectory(); if (directory == NULL) {
Saya pikir, ada kesalahan dalam kondisi perbandingan pointer
direktori dengan nilai nol; syaratnya harus sebaliknya. Dengan implementasi saat ini, jika variabel
dryRun salah , penunjuk 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 dengan nol dan tetap dengan nilai seperti itu, karena pointer tidak berubah dalam fungsi GetInput. Dalam metode lain dari kelas
BMediaRecorder , implementasinya berbeda, misalnya:
status_t BMediaRecorder::_Connect(....) { ....
Semua sudah benar di sini, tetapi fragmen pertama harus ditulis ulang, jika tidak fungsi akan mengembalikan referensi ke objek lokal.
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)
Dalam ekspresi bersyarat di mana semua data yang salah diperiksa, penulis membuat kesalahan ketik saat memeriksa pointer
mustFree . Kemungkinan besar, fungsi harus keluar ketika memiliki nilai nol dari pointer ini:
if (size < 0 || !buffer || !mustFree)
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) { .... } .... }
Pengembang seharusnya memeriksa pointer
dir alih-alih
hilang setelah konversi tipe. Omong-omong, pengembang C # juga
sering membuat kesalahan serupa. Ini membuktikan sekali lagi bahwa beberapa kesalahan tidak bergantung 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)];
Array bdev-> nbuffersTx hanya terdiri dari 2 elemen, tetapi itu ditangani oleh konstanta BT_SCO, yaitu 3. Di sinilah indeks array pasti keluar dari batas.
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];
Indeks array lain di luar batas. Kali ini, hanya dengan satu elemen. Analisis antar prosedur membantu mengungkap kasus ketika array
ni-> ni_tx_ampdu , yang terdiri dari 16 elemen ditangani oleh indeks 16. Dalam array C dan C ++ diindeks dari nol.
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 telah mendeteksi bahwa elemen array
sc-> intrs dialamatkan oleh indeks yang tidak valid, yang di luar batas. Alasannya adalah urutan operasi yang salah dalam kode. Pertama, elemen tersebut dialamatkan dan kemudian muncul pemeriksaan apakah nilai indeks valid.
Beberapa orang mungkin mengatakan tidak akan ada masalah. Itu tidak menghapus nilai elemen array, itu hanya mengambil alamat sel. Tapi tidak, itu bukan cara untuk melakukan sesuatu. Baca selengkapnya: "
Null Pointer Dereferencing Penyebab Perilaku 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. Berita baiknya adalah fungsi ini menyajikan semua konstanta yang memungkinkan yang menjadikan kode ini hanya hasil dari pemrograman Copy-Paste. Tetapi kemungkinan kesalahan akan menyelinap di sini.
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) { ....
Nah, di sini programmer mendapat nasib buruk dengan menyalin. Simbol "dot" ditambahkan ke baris dan ditulis ulang dengan terminal nol. Sangat mungkin, penulis hanya menyalin garis 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 menyebabkan dua kesalahan sekaligus. Ekspresi bersyarat identik. Kemungkinan besar, perbandingan dengan string "false" dan bukan "true" harus ada di salah satunya. Lebih jauh di cabang yang menangani nilai "false",
nilai yang harus diubah dari
1 ke
0 . Algoritme mensyaratkan bahwa nilai-nilai lain, berbeda dari
benar atau
salah dikonversi dalam angka menggunakan fungsi
atoi . Tetapi karena kesalahan, teks "false" akan masuk ke fungsi.
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); }
Penganalisa mendeteksi bahwa nilai variabel
kesalahan akan selalu menjadi
B_OK . Paling pasti, modifikasi variabel ini tidak terjawab di 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)
Kemungkinan besar bahwa dalam ekspresi bersyarat yang terakhir seseorang lupa menempatkan tanda kurung, seperti pada kondisi di atas. Operator pelengkap cenderung berada di luar kurung:
if (!(x & 1))
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 tergantung pada nilai nilai B_OK. Jadi bisa disederhanakan:
If (result != B_BUSY) break;
Anda dapat dengan mudah memeriksanya dengan menggambar tabel kebenaran untuk nilai-nilai variabel
hasil . Jika seseorang ingin secara khusus mempertimbangkan nilai-nilai lain, berbeda dari
B_OK dan
B_BUSY , kode harus ditulis ulang dengan cara lain.
Dua fragmen 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; } .... }
Ini mungkin contoh paling sederhana yang menunjukkan kerja diagnostik
V590 . Anda perlu menampilkan deskripsi program jika tidak ada argumen yang lulus, atau tidak ada dua. Jelas, nilai apa pun selain dua, termasuk nol, tidak akan memenuhi kondisi tersebut. Oleh karena itu, kondisi dapat disederhanakan dengan aman 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 diubah, tetapi logikanya masih 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. Itu juga dapat disederhanakan sebelum memeriksa apakah pengguna telah memilih "ya" atau tidak:
if (choice != "yes") { cerr << "MBR was NOT written" << endl; fs.close(); return B_ERROR; }
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 menemukan panggilan tidak berguna dari iterator
begin (). Saya tidak bisa membayangkan bagaimana cara memperbaiki kode. Pengembang harus memperhatikan kode 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 benar-benar 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 operator
sementara selalu salah. Karena ini, loop tidak menjalankan lebih dari satu iterasi. Dengan kata lain, tidak ada yang akan berubah jika Anda menulis
while (0) . Semua ini aneh dan kode ini mengandung kesalahan logika. Pengembang harus hati-hati mempertimbangkan cuplikan 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. Yang berarti, variabel ini dapat dimodifikasi dalam tubuh fungsi. Tetapi ada variabel lokal dengan nama yang sama, yang dimodifikasi. Dalam hal ini, semua perubahan hanya akan tetap dalam variabel lokal. Penulis kode mungkin ingin 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 pemformatan kode yang buruk. Kata kunci "menggantung" yang
lain belum mengubah logika, tetapi begitu sebuah fragmen kode dimasukkan sebelum operator
kembali , logikanya tidak akan sama.
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(); .... }
Saya menemukan banyak kasus ketika argumen fungsi ditulis ulang saat memasukkan fungsi. Perilaku ini menyesatkan pengembang lain yang menyebut fungsi 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 kesalahan yang menarik dan langka. Kami telah menambahkan beberapa contoh kesalahan ke basis data kami dan memperbaiki beberapa masalah analisa yang muncul saat menganalisis kode.
Jika Anda belum memeriksa kode Anda dengan beberapa alat analisis kode untuk waktu yang lama, maka beberapa masalah yang saya jelaskan mungkin bersembunyi di kode Anda. Gunakan PVS-Studio di proyek Anda (jika ditulis dalam C, C ++, C # atau Java) untuk mengontrol kualitas kode. Unduh penganalisa di
sini tanpa registrasi atau sms.
Apakah Anda ingin mencoba Haiku dan Anda memiliki pertanyaan? Pengembang Haiku mengundang Anda ke
saluran telegram .