Zahlreiche Tippfehler und Copy-Paste-Code wurden zum Thema eines zusätzlichen Artikels über die Überprüfung des Haiku-Codes durch den PVS-Studio-Analysator. Es wird jedoch Fehler geben, die weniger mit Tippfehlern als vielmehr mit Nachlässigkeit und erfolglosem Refactoring verbunden sind. Die Beispiele für gefundene Fehler zeigen, wie stark der menschliche Faktor in der Softwareentwicklung ist.
Einführung
Haiku ist ein kostenloses Open Source-Betriebssystem für PCs. Derzeit arbeitet eine internationale Gruppe von Entwicklern aktiv an den Komponenten des Systems. Zu den letzten bedeutenden Entwicklungen in der Entwicklung gehörten die Portierung von LibreOffice auf das Betriebssystem und die Veröffentlichung der ersten Beta-Version von R1 Beta 1.
Das Entwicklerteam des statischen Code-Analysators
PVS-Studio überwacht die Entwicklung des Projekts seit 2015 und veröffentlicht Überprüfungen von Codefehlern. Dies ist die vierte Überprüfung aller Zeiten. Sie können frühere Artikel unter folgenden Links kennenlernen:
- Überprüfen des Haiku-Betriebssystems (BeOS-Familie). Teil 1
- Überprüfen des Haiku-Betriebssystems (BeOS-Familie). Teil 2 ;
- Wie man sich in C und C ++ in den Fuß schießt. Haiku OS Rezeptsammlung
Ein Merkmal der neuesten Code-Analyse ist die Möglichkeit, die offizielle Version von PVS-Studio für Linux zu verwenden. Im Jahr 2015 war es nicht da, sowie ein praktischer Bericht zum Anzeigen von Fehlern. Jetzt senden wir den Entwicklern einen vollständigen Bericht in einem praktischen Format.
Klassiker des Genres
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 Programmierer in seinem Leben muss die Variablen
a und
b ,
x und
y ,
i und
j ... usw. 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; }
Unter dieser Bedingung wird derselbe
Eingabezeiger zweimal überprüft, und der
Ausgabezeiger bleibt deaktiviert, was zur Dereferenzierung des Nullzeigers führen kann.
Korrigierter 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 verlor seine Bedeutung, als der Programmierer 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
Reset- Funktion ist ein Fehler
aufgetreten : ein Tippfehler im Index der Variablen
m_kindex2 . Der Wert dieser Variablen 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 werden sofort dieselben Variablen verglichen und dieselben Variablen zugewiesen. Ich kann nicht davon ausgehen, woran hier gedacht wurde. Markieren Sie das Fragment einfach als verdächtig.
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 auf 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 auf Null initialisiert und dann beim Eingeben des
switch-Anweisungszweigs überprüft, jedoch nicht in allen Fällen. Der Analysator warnt davor, dass beim
Wechseln zum Label
USB_DESCRIPTOR_ENDPOINT_COMPANION ein Nullzeiger dereferenziert werden 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 glaube, dass es einen Fehler beim Vergleichen des
Verzeichniszeigers mit einem Nullwert gab und die Bedingung das Gegenteil sein sollte. Wenn in 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 auf Null initialisiert und bleibt auf diesem Wert, weil In der GetInput-Funktion ändert sich der Zeiger nicht. Andere Methoden der
BMediaRecorder- Klasse schreiben anders, zum Beispiel:
status_t BMediaRecorder::_Connect(....) { ....
Hier ist alles korrekt, aber es ist unmöglich, im ersten Codefragment so zu schreiben, sonst gibt die Funktion einen Link zum lokalen Objekt zurück, aber irgendwie muss der Code repariert werden.
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 ungültigen Eingabedaten überprüft werden, wurde beim Überprüfen des
mustFree- Zeigers ein Tippfehler gemacht. Höchstwahrscheinlich sollte der Ausgang der Funktion den Nullwert dieses Zeigers haben:
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) { .... } .... }
Anstelle des
fehlenden Zeigers sollten Sie den
Verzeichniszeiger nach der Typkonvertierung überprüfen. Übrigens machen C # -Programmierer
oft einen ähnlichen Fehler. Dies zeigt einmal mehr, dass einige Fehler unabhängig von der verwendeten Sprache sind.
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 zwei Elementen, während im Code auf die Konstante BT_SCO zugegriffen wird, die den Wert 3 hat. Ein garantierter Exit über die Grenzen des Arrays hinaus erfolgt.
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 anderer Ausweg aus dem Array. In diesem Fall nur ein Artikel. Die interprozedurale Analyse half dabei, eine Situation zu identifizieren, in der auf das aus 16 Elementen bestehende Array
ni-> ni_tx_ampdu am Index
16 zugegriffen wurde . In C und C ++ erfolgt die Array-Indizierung von Grund auf neu.
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 einen Aufruf des
sc-> intrs-Arrays an einem ungültigen Index festgestellt (der über die Grenzen des Arrays hinausgeht). Der Grund dafür ist die falsche Codereihenfolge. Hier wird zuerst auf das Array zugegriffen, und dann wird geprüft, ob der Indexwert gültig ist.
Jemand könnte sagen, dass es keine Probleme geben wird. Hier wird schließlich nicht der Wert des Array-Elements abgerufen, sondern die Zellenadresse wird einfach genommen. Nein, das kannst du sowieso nicht. Lesen Sie mehr: "Das
Dereferenzieren eines Nullzeigers führt zu undefiniertem 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. Glücklicherweise werden alle möglichen Konstanten in dieser Funktion dargestellt, und der Code ist einfach das Ergebnis der Copy-Paste-Programmierung. Die Wahrscheinlichkeit, auf diese Weise Fehler zu machen, ist jedoch sehr hoch.
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) { ....
Und hier hatte der Entwickler kein Glück mit dem Kopieren. Das Symbol "Punkt" wird zu einer bestimmten Zeile hinzugefügt und sofort durch eine Klemme Null überschrieben. Höchstwahrscheinlich hat der Autor des Codes die Zeichenfolge kopiert und vergessen, 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 sofortige Kopieren des Codes führte zu zwei Fehlern. Bedingte Ausdrücke sind identisch. Höchstwahrscheinlich sollte einer von ihnen einen Vergleich mit der Zeichenfolge "false" anstelle von "true" haben. Als nächstes sollten Sie in dem Zweig, der den Wert "false" verarbeitet, den
Wert von
1 auf
0 ändern. Der Algorithmus geht davon aus, dass andere Werte als
true oder
false mithilfe der
atoi- Funktion in eine Zahl
konvertiert werden. Aufgrund eines Fehlers erhält der Text jedoch auch den Text „false“.
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 . Höchstwahrscheinlich wurde eine Änderung dieser Variablen 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)
Höchstwahrscheinlich haben sie im letzten bedingten Ausdruck vergessen, Klammern zu setzen, wie in den obigen Bedingungen. Wahrscheinlich sollte sich auch dort der Negationsoperator außerhalb der Klammern befinden:
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 von B_OK ab. Somit kann es vereinfacht werden:
If (result != B_BUSY) break;
Dies kann leicht überprüft werden, indem eine Wahrheitstabelle für die Werte der
Ergebnisvariablen erstellt wird. Wenn Sie andere Werte als
B_OK und
B_BUSY berücksichtigen müssen , sollte der Code anders geschrieben werden.
Zwei weitere ähnliche Bedingungen:
- 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; } .... }
Vielleicht ist dies das einfachste Beispiel, das die Funktionsweise der
V590- Diagnose demonstriert. Die Beschreibung des Programms muss angezeigt werden, wenn keine oder zwei Argumente übergeben wurden. Offensichtlich erfüllen andere Werte als zwei, einschließlich Null, die Bedingung nicht. Daher kann die Bedingung leicht auf Folgendes 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 hat sich der logische Operator geändert, die Logik ist jedoch dieselbe geblieben. 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, um zu überprüfen, ob der Benutzer "Ja" ausgewählt hat oder nicht:
if (choice != "yes") { cerr << "MBR was NOT written" << endl; fs.close(); return B_ERROR; }
Verschiedene Fehler
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 hat einen bedeutungslosen Aufruf des Iterators
begin () festgestellt
. Ich kann nicht erraten, wie der Code repariert werden soll. Der Entwickler sollte auf diesen Ort achten.
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
GetSIMDFormatByteSize- Funktion gibt tatsächlich
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 die Bedingung der
while- Anweisung immer falsch ist. Aus diesem Grund wird nicht mehr als eine Iteration in einer Schleife ausgeführt. Mit anderen Worten, nichts würde sich ändern, wenn Sie
während (0) schreiben. All dies ist sehr seltsam und dieser Code enthält eine Art Fehler in der Arbeitslogik. Entwickler sollten auf diesen Ort achten.
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 es möglich ist, diese Variable im Hauptteil der Funktion zu ändern. Hier gibt es jedoch eine lokale Variable mit demselben Namen, die geändert wird. In diesem Fall bleiben alle Änderungen nur in der lokalen Variablen. Vielleicht sollten Sie die lokale Variable umbenennen oder löschen.
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; }
Ein Beispiel für schlechtes Code-Design. Das Schlüsselwort "eingefroren"
else ändert die Logik noch nicht, dies jedoch bis zum ersten Code, der vor der
return-Anweisung eingefügt wird.
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(); .... }
Es gab viele Fälle, in denen Funktionsargumente unmittelbar am Eingang der Funktion überschrieben wurden. Dieses Verhalten ist für andere Entwickler, die dieselben Funktionen aufrufen, irreführend.
Die ganze 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 unsere Datenbank mit Fehlerbeispielen aufgefüllt und einige Probleme im Analysator behoben, die während der Codeanalyse festgestellt wurden.
Wenn Sie Ihren Code lange Zeit nicht mit Code-Analyse-Tools überprüft haben, befindet sich wahrscheinlich auch etwas der beschriebenen in Ihrem Code. Verwenden Sie PVS-Studio in Ihrem Projekt, um die Qualität des Codes zu steuern, wenn dieser in C, C ++, C # oder Java geschrieben ist. Sie können den Analysator ohne Registrierung und SMS
hier herunterladen.
Möchten Sie Haiku ausprobieren und haben Sie Fragen? Haiku-Entwickler laden Sie zum
Telegrammkanal ein .

Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: Svyatoslav Razmyslov.
Beste Copy-Paste-Algorithmen für C und C ++. Haiku OS Kochbuch