Zahlreiche Tippfehler und Copy-Paste-Code wurden zum Hauptthema des zusätzlichen Artikels über die Überprüfung des Haiku-Codes durch den PVS-Studio-Analysator. In diesem Artikel geht es jedoch hauptsächlich um Fehler im Zusammenhang mit Gedankenlosigkeit und fehlgeschlagenem Refactoring und nicht um Tippfehler. Die gefundenen Fehler zeigen, wie stark der menschliche Faktor in der Softwareentwicklung ist.
Einführung
Haiku ist ein kostenloses Open Source-Betriebssystem für PCs. Ein internationales Entwicklungsteam arbeitet derzeit an den Komponenten des Systems. Die Portierung von Libre Office in das Betriebssystem und die erste Version von R1 Beta 1 zeichnen sich durch die jüngsten bedeutenden Entwicklungsverbesserungen aus.
Das Entwicklerteam von
PVS-Studio verfolgt diese Projektentwicklung seit 2015 und veröffentlicht Überprüfungen von Codefehlern. Dies ist die vierte Überprüfung aller Zeiten. Sie können die vorherigen Artikel über diese Links lesen:
- Analyse des Haiku-Betriebssystems (BeOS-Familie) durch PVS-Studio, Teil 1 ;
- Analyse des Haiku-Betriebssystems (BeOS-Familie) durch PVS-Studio. Teil 2 ;
- Wie man sich in C und C ++ in den Fuß schießt. Haiku OS Kochbuch
Das Merkmal der letzten Code-Analyse ist die Möglichkeit, die offizielle Version von PVS-Studio für Linux zu verwenden. Weder PVS-Studio für Linux noch ein praktischer Bericht zum Anzeigen von Fehlern waren 2015 verfügbar. Dieses Mal senden wir den vollständigen Bericht in einem praktischen Format an Haiku-Entwickler.
Klassisch
V501 Links und rechts vom Operator '-' befinden sich identische Unterausdrücke: (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; }
Jeder Entwickler muss die Variablen
a und
b ,
x und
y ,
i und
j ... mindestens einmal in seinem Leben verwechseln.
V501 Links und rechts vom '||' befinden sich identische Unterausdrücke. Operator: Eingabe == __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; }
Der gleiche
Eingabezeiger wird in der Bedingung zweimal überprüft. Während der
Ausgabezeiger deaktiviert blieb, kann dies zu einer Nullzeiger-Dereferenzierung führen.
Fester Code:
if (input == NULL || output == NULL) return B_ERROR;
V583 Der Operator '?:'
Gibt unabhängig von seinem bedingten Ausdruck immer ein und denselben Wert zurück: 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); .... }
Der ternäre Operator wurde sinnlos, als der Code-Autor einen Fehler machte und zwei identische Rückgabewerte schrieb -
500000 .
V519 Der Variablen 'm_kindex1' werden zweimal hintereinander Werte zugewiesen. Vielleicht ist das ein Fehler. Überprüfen Sie die Zeilen: 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; }
Bei der
Rücksetzfunktion ist ein Fehler
aufgetreten : ein Tippfehler im Variablenindex
m_kindex2 . Diese Variable wird nicht zurückgesetzt, was sich wahrscheinlich auf die Ausführung anderer Codefragmente auswirkt.
V501 Links und rechts vom Operator '>' befinden sich identische Unterausdrücke: 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]; .... }
In den letzten Zeilen gibt es zwei Probleme gleichzeitig: Vergleich und Zuweisung gleicher Variablen. Ich kann nicht einmal vorschlagen, was die Idee des Autors war. Ich werde diesen Ausschnitt nur als verdächtig bezeichnen.
V570 Die Variable 'wPipeIndex' wird sich selbst zugewiesen. CEchoGals_transport.cpp 244
ECHOSTATUS CEchoGals::CloseAudio (....) { .... wPipeIndex = wPipeIndex; m_ProcessId[ wPipeIndex ] = NULL; m_Pipes[ wPipeIndex ].wInterleave = 0; .... }
Die Variable
wPipeIndex wird durch ihren eigenen Wert initialisiert. Höchstwahrscheinlich wurde ein Tippfehler gemacht.
Fehler mit Zeigern
V522 Eine Dereferenzierung des Nullzeigers 'currentInterface' kann stattfinden. Device.cpp 258
Device::Device(....) : .... { .... usb_interface_info* currentInterface = NULL;
Der
currentInterface- Zeiger wird zunächst mit null initialisiert und dann beim Eingeben in die Zweige des
Switch- Operators überprüft, jedoch nicht in allen Fällen. Der Analysator warnt davor, dass beim
Wechseln zur
Fallbezeichnung USB_DESCRIPTOR_ENDPOINT_COMPANION eine Nullzeiger-Dereferenzierung auftreten kann.
V522 Es kann zu einer Dereferenzierung des Nullzeigers 'Verzeichnis' kommen. PathMonitor.cpp 1465
bool PathHandler::_EntryCreated(....) { .... Directory* directory = directoryNode->ToDirectory(); if (directory == NULL) {
Ich denke, es gibt einen Fehler in der Vergleichsbedingung des
Verzeichniszeigers mit dem Nullwert; Die Bedingung muss das Gegenteil sein. Wenn bei der aktuellen Implementierung die Variable
dryRun false ist , wird der
Verzeichnis- Nullzeiger dereferenziert.
V522 Eine Dereferenzierung des Nullzeigers 'Eingabe' kann stattfinden. MediaRecorder.cpp 343
void GetInput(media_input* input); const media_input& BMediaRecorder::MediaInput() const { CALLED(); media_input* input = NULL; fNode->GetInput(input); return *input; }
Der
Eingabezeiger wird mit null initialisiert und bleibt bei diesem Wert, da sich der Zeiger in der GetInput-Funktion nicht ändert. Bei anderen Methoden der
BMediaRecorder- Klasse ist die Implementierung anders, zum Beispiel:
status_t BMediaRecorder::_Connect(....) { ....
Hier ist alles korrekt, aber das erste Fragment muss neu geschrieben werden, sonst gibt die Funktion einen Verweis auf ein lokales Objekt zurück.
V522 Eine Dereferenzierung des Nullzeigers 'mustFree' kann stattfinden. RequestUnflattener.cpp 35
status_t Reader::Read(int32 size, void** buffer, bool* mustFree) { if (size < 0 || !buffer || mustFree)
In dem bedingten Ausdruck, in dem alle falschen Daten überprüft werden, hat der Autor beim Überprüfen des
mustFree- Zeigers einen Tippfehler
gemacht . Höchstwahrscheinlich sollte die Funktion beendet werden, wenn der Nullwert dieses Zeigers vorliegt:
if (size < 0 || !buffer || !mustFree)
V757 Es ist möglich, dass eine falsche Variable nach der Typkonvertierung mit 'dynamic_cast' mit nullptr verglichen wird. Überprüfen Sie die Zeilen: 474, 476. recovery.cpp 474
void checkStructure(Disk &disk) { .... Inode* missing = gMissing.Get(run); dir = dynamic_cast<Directory *>(missing); if (missing == NULL) { .... } .... }
Der Entwickler sollte den
Verzeichniszeiger überprüft haben, anstatt nach der Typkonvertierung zu
fehlen . Übrigens machen C # -Entwickler
oft auch einen ähnlichen Fehler. Dies zeigt einmal mehr, dass einige Fehler nicht von der verwendeten Sprache abhängen.
Noch ein paar ähnliche Stellen im Code:
- V757 Es ist möglich, dass eine falsche Variable nach der Typkonvertierung mit 'dynamic_cast' mit nullptr verglichen wird. Überprüfen Sie die Zeilen: 355, 357. ExpandoMenuBar.cpp 355
- V757 Es ist möglich, dass eine falsche Variable nach der Typkonvertierung mit 'dynamic_cast' mit nullptr verglichen wird. Überprüfen Sie die Zeilen: 600, 601. ValControl.cpp 600
Indexfehler
V557 Array-Überlauf ist möglich. Der 'BT_SCO'-Index zeigt über die Array-Grenze hinaus. h2upper.cpp 75
struct bt_usb_dev { .... struct list nbuffersTx[(1 + 1 + 0 + 0)];
Das Array
bdev-> nbuffersTx besteht nur aus 2 Elementen, wird jedoch von der Konstante BT_SCO (3) adressiert. Hier kommt der todsichere Array-Index außerhalb der Grenzen.
V557 Array-Überlauf ist möglich. Die Funktion 'ieee80211_send_setup' verarbeitet den Wert '16'. Untersuchen Sie das vierte Argument. Überprüfen Sie die Zeilen: 842, 911. ieee80211_output.c 842
struct ieee80211_node { .... struct ieee80211_tx_ampdu ni_tx_ampdu[16];
Ein weiterer Array-Index außerhalb der Grenzen. Diesmal nur um ein Element. Die interprozedurale Analyse half dabei, den Fall
aufzudecken , in dem das aus 16 Elementen bestehende Array
ni-> ni_tx_ampdu vom Index 16 adressiert wurde. In C und C ++ werden Arrays von Null indiziert.
V781 Der Wert der Variablen 'vector' wird nach ihrer Verwendung überprüft. Möglicherweise liegt ein Fehler in der Programmlogik vor. Überprüfen Sie die Zeilen: 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); .... }
Der Analysator hat festgestellt, dass ein Element des
sc-> intrs- Arrays durch einen ungültigen Index adressiert wurde, der außerhalb der Grenzen lag. Der Grund ist die falsche Reihenfolge der Operationen im Code. Zuerst wird das Element adressiert und dann wird geprüft, ob der Indexwert gültig ist.
Einige könnten sagen, dass es keine Probleme geben wird. Der Wert des Array-Elements wird nicht entfernt, sondern nur die Adresse der Zelle. Aber nein, das ist nicht der Weg, Dinge zu tun. Lesen Sie mehr: "
Null-Zeiger-Dereferenzierung verursacht undefiniertes Verhalten ".
V519 Der Variablen werden zweimal hintereinander Werte zugewiesen. Vielleicht ist das ein Fehler. Überprüfen Sie die Zeilen: 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; }
Dem Array-Element mit dem Index
NVME_INTEL_FEAT_MAX_LBA wird der gleiche Wert zugewiesen. Die gute Nachricht ist, dass diese Funktion alle möglichen Konstanten darstellt, wodurch dieser Code nur das Ergebnis der Copy-Paste-Programmierung ist. Aber es besteht die Möglichkeit, dass sich hier Fehler einschleichen.
V519 Der Variablen 'copiedPath [len]' werden zweimal hintereinander Werte zugewiesen. Vielleicht ist das ein Fehler. Überprüfen Sie die Zeilen: 92, 93. kernel_emu.cpp 93
int UserlandFS::KernelEmu::new_path(const char *path, char **copy) { ....
Nun, hier hatte der Programmierer Pech beim Kopieren. Das Symbol "Punkt" wird einer Zeile hinzugefügt und mit einem Terminal Null neu geschrieben. Es ist sehr wahrscheinlich, dass der Autor gerade die Zeile kopiert und vergessen hat, den Index zu erhöhen.
Seltsame Bedingungen
V517 Die Verwendung des
Musters 'if (A) {...} else if (A) {...}' wurde erkannt. Es besteht die Wahrscheinlichkeit eines logischen Fehlers. Überprüfen Sie die Zeilen: 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; } .... }
Das Kopieren des Codes führte zu zwei Fehlern gleichzeitig. Die bedingten Ausdrücke sind identisch. Höchstwahrscheinlich muss ein Vergleich mit der Zeichenfolge "false" anstelle von "true" in einer davon erfolgen. Weiter in dem Zweig, der den "falschen" Wert behandelt, den
Wert , der von
1 auf
0 geändert werden sollte. Der Algorithmus erfordert, dass alle anderen Werte, die sich von
wahr oder
falsch unterscheiden , mithilfe der
atoi- Funktion in eine Zahl
konvertiert werden. Aufgrund eines Fehlers wird jedoch der Text "false" in die Funktion übernommen.
V547 Der Ausdruck 'error == ((int) 0)' ist immer wahr. 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); }
Der Analysator hat festgestellt, dass der Wert der
Fehlervariablen immer
B_OK ist . Diese Variablenänderung wurde definitiv in der
while- Schleife übersehen.
V564 Der Operator '&' wird auf den Wert des
Bool- Typs angewendet. Sie haben wahrscheinlich vergessen, Klammern einzufügen, oder wollten den Operator '&&' verwenden. strtod.c 545
static int lo0bits(ULong *y) { int k; ULong x = *y; .... if (!(x & 1)) { k++; x >>= 1; if (!x & 1)
Es ist sehr wahrscheinlich, dass man im letzten bedingten Ausdruck vergessen hat, Klammern zu setzen, wie in den obigen Bedingungen. Der komplementäre Operator befindet sich wahrscheinlich außerhalb der Klammern:
if (!(x & 1))
V590 Überprüfen Sie diesen Ausdruck. Der Ausdruck ist übertrieben oder enthält einen Druckfehler. PoseView.cpp 5851
bool BPoseView::AttributeChanged(const BMessage* message) { .... result = poseModel->OpenNode(); if (result == B_OK || result != B_BUSY) break; .... }
Dies ist nicht offensichtlich, aber das Ergebnis der Bedingung hängt nicht vom Wert des B_OK-Werts ab. So kann es vereinfacht werden:
If (result != B_BUSY) break;
Sie können dies leicht überprüfen, indem Sie eine Wahrheitstabelle für die Werte der
Ergebnisvariablen zeichnen. Wenn Sie andere Werte als
B_OK und
B_BUSY berücksichtigen möchten , sollte der Code auf andere Weise neu geschrieben werden.
Zwei weitere ähnliche Fragmente:
- V590 Überprüfen Sie diesen Ausdruck. Der Ausdruck ist übertrieben oder enthält einen Druckfehler. Tracker.cpp 1714
- V590 Überprüfen Sie diesen Ausdruck. Der Ausdruck ist übertrieben oder enthält einen Druckfehler. if_ipw.c 1871
V590 Überprüfen Sie die 'argc == 0 || argc! = 2 'Ausdruck. Der Ausdruck ist übertrieben oder enthält einen Druckfehler. cmds.c 2667
void unsetoption(int argc, char *argv[]) { .... if (argc == 0 || argc != 2) { fprintf(ttyout, "usage: %s option\n", argv[0]); return; } .... }
Dies ist vielleicht das einfachste Beispiel, das die Arbeit der
V590- Diagnose demonstriert. Sie müssen die Programmbeschreibung anzeigen, falls keine oder zwei Argumente übergeben wurden. Offensichtlich erfüllen andere Werte als zwei, einschließlich Null, die Bedingung nicht. Daher kann die Bedingung sicher vereinfacht werden:
if (argc != 2) { fprintf(ttyout, "usage: %s option\n", argv[0]); return; }
V590 Überprüfen Sie die '* ptr =='; ' && * ptr! = '\ 0' 'Ausdruck. Der Ausdruck ist übertrieben oder enthält einen Druckfehler. 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); } .... }
In diesem Beispiel wurde der logische Operator geändert, aber die Logik ist immer noch dieselbe. Hier hängt die Bedingung der while-Schleife nur davon ab, ob das Zeichen
SEMI_COLON entspricht oder nicht.
V590 Überprüfen Sie diesen Ausdruck. Der Ausdruck ist übertrieben oder enthält einen Druckfehler. 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; } .... }
In diesem Beispiel gibt es bereits drei Bedingungen. Es kann auch vereinfacht werden, bevor überprüft wird, ob der Benutzer "Ja" gewählt hat oder nicht:
if (choice != "yes") { cerr << "MBR was NOT written" << endl; fs.close(); return B_ERROR; }
Verschiedenes
V530 Der Rückgabewert der Funktion 'begin' muss verwendet werden. 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();
Der Analysator fand einen sinnlosen Aufruf des Iterators
begin (). Ich kann mir nicht vorstellen, wie ich den Code reparieren soll. Entwickler sollten diesen Code beachten.
V609 Durch Null teilen. Nennerbereich [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);
Die Funktion
GetSIMDFormatByteSize gibt wirklich
0 als Standardwert zurück, was möglicherweise zu einer Division durch Null führen kann.
V654 Die Bedingung 'spezifischSequenz! = Sequenz' der Schleife ist immer falsch. 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; }
Der Analysator hat Recht, dass der Zustand des
while- Operators immer falsch ist. Aus diesem Grund führt die Schleife nicht mehr als eine Iteration aus. Mit anderen Worten, nichts würde sich ändern, wenn Sie
while (0) schreiben würden. All dies ist seltsam und dieser Code enthält einen logischen Fehler. Entwickler sollten dieses Snippet sorgfältig prüfen.
V672 Die neue Variable 'path' muss hier wahrscheinlich nicht erstellt werden. Eines der Argumente der Funktion hat denselben Namen und dieses Argument ist eine Referenz. Überprüfen Sie die Zeilen: 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; } } .... }
Die
Pfadvariable wird als Referenz an die
FindPath- Funktion übergeben. Dies bedeutet, dass diese Variable im Hauptteil der Funktion geändert werden kann. Es gibt jedoch eine lokale Variable mit demselben Namen, die geändert wird. In diesem Fall bleiben alle Änderungen nur in der lokalen Variablen. Der Code-Autor möchte möglicherweise die lokale Variable umbenennen oder entfernen.
V705 Es ist möglich, dass der Block 'else' vergessen oder
auskommentiert wurde, wodurch die Betriebslogik des Programms geändert wurde. 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; }
Das Beispiel einer schlechten Code-Formatierung. Das Schlüsselwort "hängen" ändert die Logik noch nicht, aber sobald ein Codefragment vor dem
Rückgabeoperator eingefügt wird, ist die Logik nicht mehr dieselbe.
V763 Der Parameter 'menu' wird vor der Verwendung immer im Funktionskörper neu geschrieben. video.cpp 648
bool video_mode_hook(Menu *menu, MenuItem *item) { video_mode *mode = NULL; menu = item->Submenu(); item = menu->FindMarked(); .... }
Ich habe viele Fälle gefunden, in denen Funktionsargumente beim Eingeben der Funktion neu geschrieben werden. Dieses Verhalten führt andere Entwickler in die Irre, die genau diese Funktionen aufrufen.
Die gesamte Liste der verdächtigen Orte:
- V763 Der Parameter 'force_16bit' wird vor seiner Verwendung immer im Funktionskörper neu geschrieben. ata_adapter.cpp 151
- V763 Der Parameter 'force_16bit' wird vor seiner Verwendung immer im Funktionskörper neu geschrieben. ata_adapter.cpp 179
- V763 Der Parameter 'menu' wird vor der Verwendung immer im Funktionskörper neu geschrieben. video.cpp 264
- V763 Der Parameter 'Länge' wird vor der Verwendung immer im Funktionskörper neu geschrieben. MailMessage.cpp 677
- V763 Der Parameter 'entry' wird vor seiner Verwendung immer im Funktionskörper neu geschrieben. IconCache.cpp 773
- V763 Der Parameter 'entry' wird vor seiner Verwendung immer im Funktionskörper neu geschrieben. IconCache.cpp 832
- V763 Der Parameter 'entry' wird vor seiner Verwendung immer im Funktionskörper neu geschrieben. IconCache.cpp 864
- V763 Der Parameter 'rect' wird vor der Verwendung immer in den Funktionskörper umgeschrieben. ErrorLogWindow.cpp 56
- V763 Der Parameter 'updateRect' wird vor seiner Verwendung immer im Funktionskörper neu geschrieben. CalendarMenuWindow.cpp 49
- V763 Der Parameter 'rect' wird vor der Verwendung immer in den Funktionskörper umgeschrieben. MemoryView.cpp 165
- V763 Der Parameter 'rect' wird vor der Verwendung immer in den Funktionskörper umgeschrieben. TypeEditors.cpp 1124
- V763 Der Parameter 'height' wird vor der Verwendung immer im Funktionskörper neu geschrieben. Workspaces.cpp 857
- V763 Der Parameter 'width' wird vor der Verwendung immer im Funktionskörper neu geschrieben. Workspaces.cpp 856
- V763 Der Parameter 'frame' wird vor seiner Verwendung immer im Funktionskörper neu geschrieben. SwatchGroup.cpp 48
- V763 Der Parameter 'frame' wird vor seiner Verwendung immer im Funktionskörper neu geschrieben. PlaylistWindow.cpp 89
- V763 Der Parameter 'rect' wird vor der Verwendung immer in den Funktionskörper umgeschrieben. ConfigView.cpp 78
- V763 Der Parameter 'm' wird vor seiner Verwendung immer im Funktionskörper neu geschrieben. mkntfs.c 3917
- V763 Der Parameter 'rxchainmask' wird vor der Verwendung immer im Funktionskörper neu geschrieben. ar5416_cal.c 463
- V763 Der Parameter 'c' wird vor seiner Verwendung immer im Funktionskörper neu geschrieben. if_iwn.c 6854
Fazit
Das Haiku-Projekt ist eine Quelle interessanter und seltener Fehler. Wir haben unserer Datenbank einige Fehlerbeispiele hinzugefügt und einige Probleme mit dem Analysator behoben, die bei der Analyse des Codes aufgetreten sind.
Wenn Sie Ihren Code lange Zeit nicht mit einigen Code-Analyse-Tools überprüft haben, verbergen sich einige der von mir beschriebenen Probleme wahrscheinlich in Ihrem Code. Verwenden Sie PVS-Studio in Ihrem Projekt (falls in C, C ++, C # oder Java geschrieben), um die Codequalität zu steuern. Laden Sie den Analysator
hier ohne Registrierung oder SMS herunter.
Möchten Sie Haiku ausprobieren und haben Fragen? Haiku-Entwickler laden Sie zum
Telegrammkanal ein .