Los mejores algoritmos de copiar y pegar para C y C ++. Colección de Recetas Haiku OS

Numerosos errores tipográficos y código Copy-Paste se convirtieron en el tema de un artículo adicional sobre la verificación del código Haiku por el analizador PVS-Studio. Sin embargo, habrá errores asociados no tanto con errores tipográficos, sino con descuido y refactorización fallida. Los ejemplos de errores encontrados demuestran cuán fuerte es el factor humano en el desarrollo de software.

Imagen 1

Introduccion


Haiku es un sistema operativo gratuito y de código abierto para computadoras personales. Actualmente, un grupo internacional de desarrolladores está trabajando activamente en los componentes del sistema. De los últimos desarrollos significativos en el desarrollo fue portar LibreOffice al sistema operativo y el lanzamiento de la primera versión beta de R1 Beta 1.

El equipo de desarrolladores del analizador de código estático PVS-Studio supervisa el desarrollo del proyecto desde 2015 y publica revisiones de defectos de código. Esta es la cuarta revisión de todos los tiempos. Puede familiarizarse con artículos anteriores en estos enlaces:

  1. Comprobación del sistema operativo Haiku (familia BeOS). Parte 1
  2. Comprobación del sistema operativo Haiku (familia BeOS). Parte 2 ;
  3. Cómo dispararte en el pie en C y C ++. Colección de Recetas Haiku OS

Una característica del último análisis de código es la capacidad de usar la versión oficial de PVS-Studio para Linux. En 2015, no estaba allí, así como un informe conveniente para ver los errores. Ahora enviaremos a los desarrolladores un informe completo en un formato conveniente.

Clásicos del género


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 programador en su vida debe mezclar las variables a y b , x e y , i y j ... etc.

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; } 

En esta condición, el mismo puntero de entrada se verifica dos veces, y el puntero de salida permanece sin marcar, lo que puede conducir a la desreferenciación del puntero nulo.

Código corregido:

 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 perdió su significado cuando el programador 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; } 

Se cometió un error en la función de reinicio : un error tipográfico en el índice de m_kindex2 . El valor de 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 una comparación inmediata de las mismas variables y la asignación de las mismas variables. No puedo asumir lo que se pensó aquí. Simplemente marque el 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 a 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 a cero y luego se verifica al ingresar la rama de instrucción de cambio , pero no en todos los casos. El analizador advierte que al pasar a la etiqueta USB_DESCRIPTOR_ENDPOINT_COMPANION , es posible desreferenciar un 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 hubo un error al comparar el puntero del directorio con un valor nulo y la condición debería ser la opuesta. En 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 a cero y permanece en ese valor, porque en la función GetInput, el puntero no cambia. Otros métodos de la clase BMediaRecorder escriben de manera diferente, por ejemplo:

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

Aquí todo es correcto, pero es imposible escribir así en el primer fragmento de código; de lo contrario, la función devolverá un enlace al objeto local, pero de alguna manera el código debe repararse.

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 de entrada no válidos, se realizó un error tipográfico al verificar el puntero mustFree . Lo más probable es que la salida de la función esté en el valor cero 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) { .... } .... } 

En lugar del puntero faltante , debe verificar el puntero dir después de la conversión de tipo. Por cierto, los programadores de C # a menudo cometen un error similar. Esto prueba una vez más que algunos errores son independientes del lenguaje 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 de solo dos elementos, mientras que en el código se accede por la constante BT_SCO, que tiene un valor de 3. Se produce una salida garantizada más allá de los límites de la matriz.

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 .... } 

Otra forma de salir de la matriz. En este caso, solo un artículo. El análisis interprocedimiento ayudó a identificar una situación en la que se accedió a la matriz ni-> ni_tx_ampdu , que consta de 16 elementos, en el índice 16 . En C y C ++, la indexación de matriz se realiza 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 detectó una llamada a la matriz sc-> intrs en un índice no válido (que va más allá de los límites de la matriz). La razón de esto es el orden de código incorrecto. Aquí, primero se accede a la matriz y luego se realiza una comprobación para ver si el valor del índice es válido.

Alguien puede decir que no habrá problemas. Aquí, después de todo, el valor del elemento de matriz no se recupera, sino que simplemente se toma la dirección de la celda. No, no puedes hacerlo de todos modos. Leer más: " Desreferenciar un puntero nulo conduce a 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. Afortunadamente, todas las constantes posibles están representadas en esta función, y el código es simplemente el resultado de la programación Copy-Paste. Pero la probabilidad de cometer errores de esta manera es muy alta.

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'; } .... } 

Y aquí el desarrollador no tuvo suerte con la copia. El símbolo "punto" se agrega a una determinada línea y se sobrescribe inmediatamente con un terminal cero. Muy probablemente, el autor del código copió la cadena y olvidó 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 inmediatamente condujo a dos errores. Las expresiones condicionales son idénticas. Lo más probable es que uno de ellos tenga una comparación con la cadena "falso", en lugar de "verdadero". A continuación, en la rama que procesa el valor "falso", debe cambiar el valor del valor de 1 a 0 . El algoritmo supone que cualquier otro valor que no sea verdadero o falso se convertirá en un número utilizando la función atoi , pero debido a un error, el texto también obtendrá el texto "falso".

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 . Lo más probable es que se haya pasado por alto una modificación de esta variable 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; } 

Lo más probable es que, en la última expresión condicional, olvidaron colocar corchetes, como en las condiciones anteriores. Probablemente, allí también el operador de negación debe estar 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 de B_OK. Por lo tanto, se puede simplificar:

 If (result != B_BUSY) break; 

Esto se puede verificar fácilmente construyendo una tabla de verdad para los valores de la variable de resultado . Si necesita considerar específicamente otros valores distintos de B_OK y B_BUSY , entonces el código debe reescribirse de manera diferente.

Dos condiciones 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; } .... } 

Quizás este es el ejemplo más simple que demuestra el funcionamiento del diagnóstico V590 . Es necesario mostrar la descripción del programa si no se pasan argumentos o si no hay dos. Obviamente, cualquier valor que no sea dos, incluido cero, no satisfará la condición. Por lo tanto, la condición se puede simplificar fácilmente a lo siguiente:

 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, el operador lógico ha cambiado, pero la lógica se ha mantenido igual. 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 para verificar si el usuario ha seleccionado "sí" o no:

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

Errores varios


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 detectó una llamada sin sentido al iterador begin (). No puedo adivinar cómo arreglar el código. El desarrollador debe prestar atención a este lugar.

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 en realidad 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 de la declaración while siempre es falsa. Debido a esto, no se realiza más de una iteración en un bucle. En otras palabras, nada cambiaría si escribes while (0) . Todo esto es muy extraño y este código contiene algún tipo de error en la lógica del trabajo. Los desarrolladores deben prestar atención a este lugar.

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. Esto significa que es posible modificar esta variable en el cuerpo de la función. Pero aquí hay una variable local del mismo nombre que se está modificando. En este caso, todos los cambios permanecerán solo en la variable local. Quizás debería 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; } 

Un ejemplo de diseño de código pobre. La palabra clave else "congelada" todavía no cambia la lógica, pero esto es hasta que se inserta el primer fragmento de código antes de la declaración de devolución .

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(); .... } 

Hubo muchos casos en los que los argumentos de la función se sobrescriben inmediatamente en la entrada de la función. Este comportamiento es engañoso para otros desarrolladores que invocan estas mismas 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. Reabastecimos nuestra base de datos de ejemplos de errores y solucionamos varios problemas en el analizador identificado durante el análisis de código.

Si no ha verificado su código con ninguna herramienta de análisis de código durante mucho tiempo, entonces algo de lo descrito probablemente también esté en su código. Use PVS-Studio en su proyecto para controlar la calidad del código si está escrito en C, C ++, C # o Java. Puede descargar el analizador sin registro y SMS aquí .

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



Si desea compartir este artículo con una audiencia de habla inglesa, utilice el enlace a la traducción: Svyatoslav Razmyslov. Los mejores algoritmos de copiar y pegar para C y C ++. Haiku OS Cookbook

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


All Articles