Los mejores algoritmos de copiar y pegar para C y C ++. Haiku OS Cookbook

Numerosos errores tipográficos y código Copy-Paste se convirtieron en el tema principal del artículo adicional sobre la verificación del código Haiku por el analizador PVS-Studio. Sin embargo, este artículo trata principalmente sobre errores relacionados con la falta de consideración y la refactorización fallida, en lugar de errores tipográficos. Los errores encontrados demuestran cuán fuerte es el factor humano en el desarrollo de software.

Imagen 1

Introduccion


Haiku es un sistema operativo gratuito de código abierto para computadoras personales. Un equipo de desarrollo internacional está trabajando actualmente en los componentes del sistema. Portar Libre Office en el sistema operativo y la primera versión R1 Beta 1 se destacan entre las recientes mejoras significativas de desarrollo.

El equipo de desarrolladores de PVS-Studio sigue el desarrollo de este proyecto desde 2015 y publica revisiones de defectos de código. Esta es la cuarta revisión de todos los tiempos. Puede leer los artículos anteriores en estos enlaces:

  1. Análisis del sistema operativo Haiku (Familia BeOS), por PVS-Studio, Parte 1 ;
  2. Análisis del sistema operativo Haiku (familia BeOS) por PVS-Studio. Parte 2 ;
  3. Cómo dispararte en el pie en C y C ++. Libro de cocina Haiku OS

La característica del último análisis de código es la capacidad de usar la versión oficial de PVS-Studio para Linux. Ni PVS-Studio para Linux, ni un informe conveniente para ver los errores estaban disponibles en 2015. Esta vez enviaremos el informe completo en un formato conveniente a los desarrolladores de Haiku.

Clásico


V501 Hay subexpresiones idénticas a la izquierda y a la derecha del operador '-': (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; } 

Cada desarrollador tiene que mezclar las variables a y b , x e y , i y j ... al menos una vez en su vida.

V501 Hay subexpresiones idénticas a la izquierda y a la derecha de '||' operador: 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; } 

El mismo puntero de entrada se verifica en la condición dos veces. Mientras que el puntero de salida permaneció sin marcar, lo que puede dar como resultado la anulación de la referencia del puntero.

Código fijo:

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

V583 El operador '?:', Independientemente de su expresión condicional, siempre devuelve el mismo valor: 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); .... } 

El operador ternario se volvió inútil, cuando el autor del código cometió un error y escribió dos valores de retorno idénticos: 500000 .

V519 A la variable 'm_kindex1' se le asignan valores dos veces seguidas. Quizás esto sea un error. Verifique las líneas: 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; } 

Hay un error en la función de reinicio : un error tipográfico en el índice variable m_kindex2 . Esta variable no se restablecerá, lo que probablemente afectará la ejecución de otros fragmentos de código.

V501 Hay subexpresiones idénticas a la izquierda y a la derecha del operador '>': 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]; .... } 

En las últimas líneas, hay dos problemas a la vez: comparación y asignación de variables iguales. Ni siquiera puedo sugerir cuál fue la creación del autor. Solo notaré este fragmento como sospechoso.

V570 La variable 'wPipeIndex' se asigna a sí misma. CEchoGals_transport.cpp 244

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

La variable wPipeIndex se inicializa por su propio valor. Lo más probable es que se haya cometido un error tipográfico.

Errores con punteros


V522 Puede tener lugar la desreferenciación del puntero nulo 'currentInterface'. 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; .... } .... } 

El puntero currentInterface se inicializa inicialmente por nulo y luego se verifica al ingresar en las ramas del operador del interruptor , pero no en todos los casos. El analizador advierte que al saltar a la etiqueta de caso USB_DESCRIPTOR_ENDPOINT_COMPANION , puede producirse una anulación de puntero nulo.

V522 Puede tener lugar la desreferenciación del puntero nulo 'directorio'. 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; } .... } 

Creo que hay un error en la condición de comparación del puntero del directorio con el valor nulo; La condición tiene que ser lo contrario. Con la implementación actual, si la variable dryRun es falsa , el puntero nulo del directorio será desreferenciado.

V522 Puede tener lugar la desreferenciación del puntero nulo 'input'. MediaRecorder.cpp 343

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

El puntero de entrada se inicializa por nulo y permanece con dicho valor, ya que el puntero no cambia en la función GetInput. En otros métodos de la clase BMediaRecorder , la implementación es diferente, por ejemplo:

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

Aquí todo es correcto, pero el primer fragmento debe reescribirse, de lo contrario la función devolverá una referencia a un objeto local.

V522 Puede tener lugar la desreferenciación del puntero nulo 'mustFree'. 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; } .... } 

En la expresión condicional donde se verifican todos los datos incorrectos, el autor cometió un error tipográfico al verificar el puntero mustFree . Lo más probable es que la función salga cuando tenga el valor nulo de este puntero:

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

V757 Es posible que una variable incorrecta se compare con nullptr después de la conversión de tipo usando 'dynamic_cast'. Líneas de verificación: 474, 476. recover.cpp 474

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

El desarrollador debería haber verificado el puntero dir en lugar de faltar después de la conversión de tipo. Por cierto, los desarrolladores de C # a menudo también cometen un error similar. Esto prueba una vez más que algunos errores no dependen del idioma utilizado.

Un par de lugares más similares en el código:

  • V757 Es posible que una variable incorrecta se compare con nullptr después de la conversión de tipo usando 'dynamic_cast'. Líneas de verificación: 355, 357. ExpandoMenuBar.cpp 355
  • V757 Es posible que una variable incorrecta se compare con nullptr después de la conversión de tipo usando 'dynamic_cast'. Líneas de verificación: 600, 601. ValControl.cpp 600

Errores de índice


V557 Array overrun es posible. El índice 'BT_SCO' apunta más allá de la matriz. 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 } .... } 

La matriz bdev-> nbuffersTx consta solo de 2 elementos, pero está dirigida por la constante BT_SCO, que es 3. Aquí viene el índice de la matriz segura fuera de límites.

V557 Array overrun es posible. La función 'ieee80211_send_setup' procesa el valor '16'. Inspeccione el cuarto argumento. Verifique las líneas: 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 .... } 

Otro índice de matriz fuera de los límites. Esta vez, solo por un elemento. El análisis interprocedural ayudó a revelar el caso cuando la matriz ni-> ni_tx_ampdu , que consta de 16 elementos, fue abordada por el índice 16. En C y C ++ las matrices se indexan desde cero.

V781 El valor de la variable 'vector' se verifica después de su uso. Quizás haya un error en la lógica del programa. Líneas de verificación: 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); .... } 

El analizador ha detectado que un elemento de la matriz sc-> intrs fue abordado por un índice no válido, que estaba fuera de los límites. La razón es el orden incorrecto de las operaciones en el código. Primero, se direcciona el elemento y luego viene la verificación de si el valor del índice es válido.

Algunos podrían decir que no habrá ningún problema. No elimina el valor del elemento de matriz, solo toma la dirección de la celda. Pero no, esa no es la forma de hacer las cosas. Leer más: "La desreferencia de puntero nulo provoca un comportamiento indefinido ".

V519 A la variable se le asignan valores dos veces seguidas. Quizás esto sea un error. Líneas de verificación: 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; } 

Al elemento de matriz con el índice NVME_INTEL_FEAT_MAX_LBA se le asigna el mismo valor. La buena noticia es que esta función presenta todas las constantes posibles, lo que hace que este código sea solo el resultado de la programación Copy-Paste. Pero es probable que los errores se cuelen aquí.

V519 La variable 'copiedPath [len]' tiene valores asignados dos veces sucesivamente. Quizás esto sea un error. Líneas de verificación: 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'; } .... } 

Bueno, aquí el programador tuvo mala suerte con la copia. El símbolo "punto" se agrega a una línea y se reescribe con un terminal nulo. Es muy probable que el autor haya copiado la línea y se haya olvidado de incrementar el índice.

Condiciones extrañas


V517 El uso del patrón 'if (A) {...} else if (A) {...}' fue detectado. Hay una probabilidad de presencia de error lógico. Líneas de verificación: 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; } .... } 

Copiar el código condujo a dos errores a la vez. Las expresiones condicionales son idénticas. Lo más probable es que una comparación con la cadena "falsa" en lugar de "verdadero" tenga que estar en una de ellas. Además en la rama que maneja el valor "falso", el valor que debe cambiarse de 1 a 0 . El algoritmo requiere que cualquier otro valor, diferente de verdadero o falso, se convierta en un número utilizando la función atoi . Pero debido a un error, el texto "falso" entrará en la función.

V547 La expresión 'error == ((int) 0)' siempre es verdadera. 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); } 

El analizador detectó que el valor de la variable de error siempre será B_OK . Definitivamente, esta modificación variable se perdió en el ciclo while.

V564 El operador '&' se aplica al valor de tipo bool. Probablemente haya olvidado incluir paréntesis o tenga la intención de utilizar el operador '&&'. 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; } 

Es muy probable que en la última expresión condicional se haya olvidado colocar corchetes, como en las condiciones anteriores. Es probable que el operador complementario esté fuera de los corchetes:

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

V590 Considere inspeccionar esta expresión. La expresión es excesiva o contiene un error de imprenta. PoseView.cpp 5851

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

Esto no es obvio, pero el resultado de la condición no depende del valor del valor B_OK. Entonces se puede simplificar:

 If (result != B_BUSY) break; 

Puede verificarlo fácilmente dibujando una tabla de verdad para los valores de la variable de resultado . Si uno quisiera considerar específicamente otros valores, diferentes de B_OK y B_BUSY , el código debe reescribirse de otra manera.

Dos fragmentos más similares:

  • V590 Considere inspeccionar esta expresión. La expresión es excesiva o contiene un error de imprenta. Tracker.cpp 1714
  • V590 Considere inspeccionar esta expresión. La expresión es excesiva o contiene un error de imprenta. if_ipw.c 1871

V590 Considere inspeccionar el 'argc == 0 || argc! = expresión de 2 '. La expresión es excesiva o contiene un error de imprenta. cmds.c 2667

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

Este es quizás el ejemplo más simple que demuestra el trabajo del diagnóstico V590 . Debe mostrar la descripción del programa en caso de que no haya argumentos aprobados o de que no haya dos. Obviamente, cualquier valor que no sea dos, incluido cero, no satisfará la condición. Por lo tanto, la condición se puede simplificar de manera segura a esto:

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

V590 Considere inspeccionar el '* ptr =='; ' && * ptr! = '\ 0' 'expresión. La expresión es excesiva o contiene un error de imprenta. 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); } .... } 

En este ejemplo, se cambió el operador lógico, pero la lógica sigue siendo la misma. Aquí la condición del ciclo while depende solo de si el carácter es igual a SEMI_COLON o no.

V590 Considere inspeccionar esta expresión. La expresión es excesiva o contiene un error de imprenta. 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; } .... } 

Ya hay tres condiciones en este ejemplo. También se puede simplificar antes de verificar si el usuario ha elegido "sí" o no:

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

Misceláneo


V530 Se requiere utilizar el valor de retorno de la función 'comenzar'. 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(); // <= } } 

El analizador encontró una llamada sin sentido del iterador begin (). No puedo imaginar cómo arreglar el código. Los desarrolladores deben prestar atención a este código.

V609 Divide por cero. Rango del denominador [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); // <= .... } 

La función GetSIMDFormatByteSize realmente devuelve 0 como valor predeterminado, lo que podría conducir a la división por cero.

V654 La condición ' SpecificSequence ! = Sequence' del bucle siempre es falsa. 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; } 

El analizador tiene razón en que la condición del operador while siempre es falsa. Debido a esto, el bucle no ejecuta más de una iteración. En otras palabras, nada cambiaría si escribiera while (0) . Todo esto es extraño y este código contiene un error lógico. Los desarrolladores deben considerar cuidadosamente este fragmento.

V672 Probablemente no sea necesario crear la nueva variable 'ruta' aquí. Uno de los argumentos de la función posee el mismo nombre y este argumento es una referencia. Líneas de verificación: 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; } } .... } 

La variable de ruta se pasa a la función FindPath por referencia. Lo que significa que esta variable se puede modificar en el cuerpo de la función. Pero hay una variable local con el mismo nombre, que se modifica. En este caso, todos los cambios permanecerán solo en la variable local. El autor del código puede querer cambiar el nombre o eliminar la variable local.

V705 Es posible que el bloque 'else' haya sido olvidado o comentado, alterando así las lógicas de operación del programa. 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; } 

El ejemplo de formato de código deficiente. La palabra clave "colgar" no cambia la lógica todavía, pero una vez que se inserta un fragmento de código antes del operador de retorno , la lógica no será la misma.

El 'menú' del parámetro V763 siempre se reescribe en el cuerpo de la función antes de usarse. video.cpp 648

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

Encontré muchos casos cuando los argumentos de la función se reescriben al ingresar a la función. Este comportamiento engaña a otros desarrolladores que llaman a estas funciones.

La lista completa de lugares sospechosos:

  • V763 El parámetro 'force_16bit' siempre se reescribe en el cuerpo de la función antes de usarse. ata_adapter.cpp 151
  • V763 El parámetro 'force_16bit' siempre se reescribe en el cuerpo de la función antes de usarse. ata_adapter.cpp 179
  • El 'menú' del parámetro V763 siempre se reescribe en el cuerpo de la función antes de usarse. video.cpp 264
  • V763 El parámetro 'length' siempre se reescribe en el cuerpo de la función antes de usarse. MailMessage.cpp 677
  • V763 El parámetro 'entrada' siempre se reescribe en el cuerpo de la función antes de ser utilizado. IconCache.cpp 773
  • V763 El parámetro 'entrada' siempre se reescribe en el cuerpo de la función antes de ser utilizado. IconCache.cpp 832
  • V763 El parámetro 'entrada' siempre se reescribe en el cuerpo de la función antes de ser utilizado. IconCache.cpp 864
  • V763 El parámetro 'rect' siempre se reescribe en el cuerpo de la función antes de usarse. ErrorLogWindow.cpp 56
  • El parámetro V763 'updateRect' siempre se reescribe en el cuerpo de la función antes de usarse. CalendarMenuWindow.cpp 49
  • V763 El parámetro 'rect' siempre se reescribe en el cuerpo de la función antes de usarse. MemoryView.cpp 165
  • V763 El parámetro 'rect' siempre se reescribe en el cuerpo de la función antes de usarse. TypeEditors.cpp 1124
  • V763 El parámetro 'altura' siempre se reescribe en el cuerpo de la función antes de usarse. Workspaces.cpp 857
  • V763 El parámetro 'ancho' siempre se reescribe en el cuerpo de la función antes de usarse. Workspaces.cpp 856
  • El parámetro 'frame' V763 siempre se reescribe en el cuerpo de la función antes de ser utilizado. SwatchGroup.cpp 48
  • El parámetro 'frame' V763 siempre se reescribe en el cuerpo de la función antes de ser utilizado. PlaylistWindow.cpp 89
  • V763 El parámetro 'rect' siempre se reescribe en el cuerpo de la función antes de usarse. ConfigView.cpp 78
  • V763 El parámetro 'm' siempre se reescribe en el cuerpo de la función antes de usarse. mkntfs.c 3917
  • El parámetro V763 'rxchainmask' siempre se reescribe en el cuerpo de la función antes de usarse. ar5416_cal.c 463
  • V763 El parámetro 'c' siempre se reescribe en el cuerpo de la función antes de usarse. if_iwn.c 6854

Conclusión


El proyecto Haiku es una fuente de errores interesantes y raros. Agregamos a nuestra base de datos algunos ejemplos de errores y solucionamos algunos problemas del analizador que aparecían al analizar el código.

Si no ha verificado su código con algunas herramientas de análisis de código durante mucho tiempo, entonces algunos de los problemas que describí probablemente estén ocultos en su código. Use PVS-Studio en su proyecto (si está escrito en C, C ++, C # o Java) para controlar la calidad del código. Descargue el analizador aquí sin registro o sms.

¿Quieres probar Haiku y tienes preguntas? Los desarrolladores de Haiku te invitan al canal de telegramas .

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


All Articles