Melhores algoritmos de copiar e colar para C e C ++. Coleção de receitas do sistema operacional Haiku

Inúmeros erros de digitação e código Copy-Paste tornaram-se o tópico de um artigo adicional sobre a verificação do código Haiku pelo analisador PVS-Studio. No entanto, haverá erros associados não tanto aos erros de digitação, mas ao descuido e à refatoração malsucedida. Os exemplos de erros encontrados demonstram a força do fator humano no desenvolvimento de software.

Quadro 1

1. Introdução


O Haiku é um sistema operacional de código aberto gratuito para computadores pessoais. Atualmente, um grupo internacional de desenvolvedores está trabalhando ativamente nos componentes do sistema. Um dos últimos desenvolvimentos significativos no desenvolvimento foi a transferência do LibreOffice para o sistema operacional e o lançamento da primeira versão beta do R1 Beta 1.

A equipe de desenvolvedores do analisador de código estático PVS-Studio monitora o desenvolvimento do projeto desde 2015, liberando análises de defeitos de código. Esta é a quarta revisão de todos os tempos. Você pode se familiarizar com os artigos anteriores nesses links:

  1. Verificando o sistema operacional Haiku (família BeOS). Parte 1
  2. Verificando o sistema operacional Haiku (família BeOS). Parte 2 ;
  3. Como dar um tiro no pé em C e C ++. Coleção de receitas do sistema operacional Haiku

Um recurso da análise de código mais recente é a capacidade de usar a versão oficial do PVS-Studio for Linux. Em 2015, ele não estava lá, além de um relatório conveniente para a visualização de erros. Agora enviaremos aos desenvolvedores um relatório completo em um formato conveniente.

Clássicos do gênero


V501 Existem subexpressões idênticas à esquerda e à direita do 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; } 

Todo programador em sua vida deve misturar as variáveis a e b , x e y , iej ... etc.

V501 Existem subexpressões idênticas à esquerda e à direita do '||' operador: input == __null || input == __nulo 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; } 

Na condição, o mesmo ponteiro de entrada é verificado duas vezes e o ponteiro de saída permanece desmarcado, o que pode levar à desreferência do ponteiro nulo.

Código corrigido:

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

V583 O operador '?:', Independentemente de sua expressão condicional, sempre retorna um e o mesmo 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); .... } 

O operador ternário perdeu o significado quando o programador cometeu um erro e escreveu dois valores de retorno idênticos - 500000 .

V519 A variável 'm_kindex1' recebe valores duas vezes sucessivamente. Talvez isso seja um erro. Verifique as linhas: 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; } 

Ocorreu um erro na função de redefinição : um erro de digitação no índice da variável m_kindex2 . O valor dessa variável não será redefinido, o que provavelmente afetará a execução de outros fragmentos de código.

V501 Existem subexpressões idênticas à esquerda e à direita do 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]; .... } 

Nas últimas linhas, há imediatamente uma comparação das mesmas variáveis ​​e atribuição das mesmas variáveis. Não posso assumir o que foi pensado aqui. Apenas marque o fragmento como suspeito.

V570 A variável 'wPipeIndex' é atribuída a si mesma. CEchoGals_transport.cpp 244

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

A variável wPipeIndex é inicializada com seu próprio valor. Provavelmente, um erro de digitação foi feito.

Erros com ponteiros


V522 A desreferenciação do ponteiro nulo 'currentInterface' pode ocorrer. 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; .... } .... } 

O ponteiro currentInterface é inicialmente inicializado como zero e depois verificado ao entrar no ramo de instrução do switch , mas não em todos os casos. O analisador avisa que, ao passar para o rótulo USB_DESCRIPTOR_ENDPOINT_COMPANION , é possível desreferenciar um ponteiro nulo.

V522 A desreferenciação do ponteiro nulo 'diretório' pode ocorrer. 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; } .... } 

Acredito que houve um erro ao comparar o ponteiro do diretório com um valor nulo e a condição deve ser o oposto. Na implementação atual, se a variável dryRun for falsa , o ponteiro nulo do diretório será desreferenciado.

V522 A desreferenciação do ponteiro nulo 'entrada' pode ocorrer. MediaRecorder.cpp 343

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

O ponteiro de entrada é inicializado em zero e permanece nesse valor, porque na função GetInput, o ponteiro não muda. Outros métodos da classe BMediaRecorder gravam de maneira diferente, por exemplo:

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

Tudo está correto aqui, mas é impossível escrever assim no primeiro fragmento de código; caso contrário, a função retornará um link para o objeto local, mas de alguma forma o código precisa ser corrigido.

V522 A desreferenciação do ponteiro nulo 'mustFree' pode ocorrer. 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; } .... } 

Na expressão condicional, onde todos os dados de entrada inválidos são verificados, um erro de digitação foi feito ao verificar o ponteiro mustFree . Provavelmente, a saída da função deve estar no valor zero deste ponteiro:

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

V757 É possível que uma variável incorreta seja comparada com nullptr após a conversão do tipo usando 'dynamic_cast'. Verifique as linhas: 474, 476. recover.cpp 474

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

Em vez do ponteiro ausente , você deve verificar o ponteiro dir após a conversão do tipo. A propósito, programadores de C # geralmente cometem um erro semelhante. Isso prova mais uma vez que alguns erros são independentes do idioma usado.

Mais alguns lugares semelhantes no código:

  • V757 É possível que uma variável incorreta seja comparada com nullptr após a conversão do tipo usando 'dynamic_cast'. Verifique as linhas: 355, 357. ExpandoMenuBar.cpp 355
  • V757 É possível que uma variável incorreta seja comparada com nullptr após a conversão do tipo usando 'dynamic_cast'. Verifique as linhas: 600, 601. ValControl.cpp 600

Erros de índice


A saturação da matriz V557 é possível. O índice 'BT_SCO' está apontando além do limite da 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 } .... } 

A matriz bdev-> nbuffersTx consiste em apenas dois elementos, enquanto no código é acessada pela constante BT_SCO, que possui um valor de 3. Ocorre uma saída garantida além dos limites da matriz.

A saturação da matriz V557 é possível. A função 'ieee80211_send_setup' processa o valor '16'. Inspecione o quarto argumento. Verifique as linhas: 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 .... } 

Outra maneira de sair da matriz. Nesse caso, apenas um item. A análise interprocedural ajudou a identificar uma situação em que o array ni-> ni_tx_ampdu , composto por 16 elementos, foi acessado no índice 16 . Em C e C ++, a indexação de matriz é feita do zero.

V781 O valor da variável 'vetor' é verificado depois que foi usado. Talvez haja um erro na lógica do programa. Verifique as linhas: 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); .... } 

O analisador detectou uma chamada para a matriz sc-> intrs com um índice inválido (indo além dos limites da matriz). A razão para isso é a ordem incorreta do código. Aqui, a matriz é acessada primeiro e, em seguida, é feita uma verificação para ver se o valor do índice é válido.

Alguém pode dizer que não haverá problemas. Aqui, afinal, o valor do elemento da matriz não é recuperado, mas o endereço da célula é simplesmente obtido. Não, você não pode fazer isso de qualquer maneira. Leia mais: " Remover a referência a um ponteiro nulo leva a um comportamento indefinido ".

V519 A variável recebe valores atribuídos duas vezes sucessivamente. Talvez isso seja um erro. Verifique as linhas: 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; } 

O elemento da matriz com o índice NVME_INTEL_FEAT_MAX_LBA recebe o mesmo valor. Felizmente, todas as constantes possíveis são representadas nessa função e o código é simplesmente o resultado da programação Copy-Paste. Mas a probabilidade de cometer erros dessa maneira é muito alta.

V519 A variável 'copiedPath [len]' recebe valores duas vezes sucessivamente. Talvez isso seja um erro. Verifique as linhas: 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'; } .... } 

E aqui o desenvolvedor não teve sorte em copiar. O símbolo "ponto" é adicionado a uma determinada linha e é imediatamente substituído por um terminal zero. Provavelmente, o autor do código copiou a string e esqueceu de incrementar o índice.

Condições estranhas


V517 O uso do padrão 'if (A) {...} else if (A) {...}' foi detectado. Há uma probabilidade de presença de erro lógico. Verifique as linhas: 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 o código imediatamente levou a dois erros. Expressões condicionais são idênticas. Provavelmente, um deles deve ter uma comparação com a string "false", em vez de "true". Em seguida, na ramificação que processa o valor "false", você deve alterar o valor do valor de 1 para 0 . O algoritmo assume que quaisquer outros valores que não sejam verdadeiros ou falsos serão convertidos em um número usando a função atoi , mas devido a um erro, o texto também receberá o texto "false".

A expressão V547 'erro == ((int) 0)' é sempre verdadeira. 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); } 

O analisador detectou que o valor da variável de erro sempre será B_OK . Provavelmente, uma modificação dessa variável foi perdida no loop while .

V564 O operador '&' é aplicado ao valor do tipo bool. Você provavelmente esqueceu de incluir parênteses ou pretende usar o 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; } 

Muito provavelmente, na última expressão condicional, eles esqueceram de colocar colchetes, como nas condições acima. Provavelmente também o operador de negação deve estar fora dos colchetes:

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

V590 Considere inspecionar esta expressão. A expressão é excessiva ou contém uma impressão incorreta. PoseView.cpp 5851

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

Isso não é óbvio, mas o resultado da condição não depende do valor de B_OK. Assim, pode ser simplificado:

 If (result != B_BUSY) break; 

Isso é facilmente verificado através da construção de uma tabela verdade para os valores da variável resultado . Se você precisar considerar especificamente outros valores além de B_OK e B_BUSY , o código deverá ser reescrito de maneira diferente.

Mais duas condições semelhantes:

  • V590 Considere inspecionar esta expressão. A expressão é excessiva ou contém uma impressão incorreta. Tracker.cpp 1714
  • V590 Considere inspecionar esta expressão. A expressão é excessiva ou contém uma impressão incorreta. if_ipw.c 1871

V590 Considere inspecionar o 'argc == 0 || argc! = 2 'expressão. A expressão é excessiva ou contém uma impressão incorreta. cmds.c 2667

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

Talvez este seja o exemplo mais simples que demonstra a operação do diagnóstico V590 . É necessário exibir a descrição do programa se não houver argumentos passados ​​ou se não houver dois deles. Obviamente, quaisquer valores que não sejam dois, incluindo zero, não satisfarão a condição. Portanto, a condição pode ser facilmente simplificada para o seguinte:

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

V590 Considere inspecionar o '* ptr =='; ' && * ptr! = '\ 0' 'expressão. A expressão é excessiva ou contém uma impressão incorreta. 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); } .... } 

Neste exemplo, o operador lógico mudou, mas a lógica permaneceu a mesma. Aqui, a condição do loop while depende apenas se o caractere é igual a SEMI_COLON ou não.

V590 Considere inspecionar esta expressão. A expressão é excessiva ou contém uma impressão incorreta. 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; } .... } 

Já existem três condições neste exemplo. Também pode ser simplificado para verificar se o usuário selecionou "yes" ou não:

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

Erros diversos


V530 O valor de retorno da função 'begin' deve ser utilizado. 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(); // <= } } 

O analisador detectou uma chamada sem sentido para o iterador begin (). Não sei como consertar o código. O desenvolvedor deve prestar atenção a este local.

V609 Divida por zero. Intervalo do 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); // <= .... } 

A função GetSIMDFormatByteSize realmente retorna 0 como o valor padrão, o que pode levar à divisão por zero.

V654 A condição 'specificSequence! = Sequence' do loop é sempre 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; } 

O analisador está certo de que a condição da instrução while é sempre falsa. Por esse motivo, não é executada mais de uma iteração em um loop. Em outras palavras, nada mudaria se você escrever enquanto (0) . Tudo isso é muito estranho e esse código contém algum tipo de erro na lógica do trabalho. Os desenvolvedores devem prestar atenção a este local.

V672 Provavelmente não há necessidade de criar a nova variável 'caminho' aqui. Um dos argumentos da função possui o mesmo nome e esse argumento é uma referência. Verifique as linhas: 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; } } .... } 

A variável de caminho é passada para a função FindPath por referência. Isso significa que é possível modificar essa variável no corpo da função. Mas aqui há uma variável local com o mesmo nome que está sendo modificada. Nesse caso, todas as alterações permanecerão apenas na variável local. Talvez você deva renomear ou excluir a variável local.

V705 É possível que o bloco 'else' tenha sido esquecido ou comentado, alterando a lógica de operação do 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; } 

Um exemplo de design de código ruim. A palavra-chave "frozen" else ainda não altera a lógica, mas isso é até o primeiro trecho de código inserido antes da instrução de retorno .

V763 O parâmetro 'menu' é sempre reescrito no corpo da função antes de ser usado. video.cpp 648

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

Houve muitos casos em que os argumentos da função são substituídos imediatamente na entrada da função. Esse comportamento é enganoso para outros desenvolvedores que invocam essas mesmas funções.

Toda a lista de lugares suspeitos:

  • V763 O parâmetro 'force_16bit' é sempre reescrito no corpo da função antes de ser usado. ata_adapter.cpp 151
  • V763 O parâmetro 'force_16bit' é sempre reescrito no corpo da função antes de ser usado. ata_adapter.cpp 179
  • V763 O parâmetro 'menu' é sempre reescrito no corpo da função antes de ser usado. video.cpp 264
  • V763 O parâmetro 'length' é sempre reescrito no corpo da função antes de ser usado. MailMessage.cpp 677
  • V763 O parâmetro 'entry' é sempre reescrito no corpo da função antes de ser usado. IconCache.cpp 773
  • V763 O parâmetro 'entry' é sempre reescrito no corpo da função antes de ser usado. IconCache.cpp 832
  • V763 O parâmetro 'entry' é sempre reescrito no corpo da função antes de ser usado. IconCache.cpp 864
  • V763 O parâmetro 'rect' é sempre reescrito no corpo da função antes de ser utilizado. ErrorLogWindow.cpp 56
  • V763 O parâmetro 'updateRect' é sempre reescrito no corpo da função antes de ser usado. CalendarMenuWindow.cpp 49
  • V763 O parâmetro 'rect' é sempre reescrito no corpo da função antes de ser utilizado. MemoryView.cpp 165
  • V763 O parâmetro 'rect' é sempre reescrito no corpo da função antes de ser utilizado. TypeEditors.cpp 1124
  • V763 O parâmetro 'height' é sempre reescrito no corpo da função antes de ser usado. Workspaces.cpp 857
  • V763 O parâmetro 'width' é sempre reescrito no corpo da função antes de ser usado. Espaços de trabalho.cpp 856
  • V763 O parâmetro 'frame' é sempre reescrito no corpo da função antes de ser usado. SwatchGroup.cpp 48
  • V763 O parâmetro 'frame' é sempre reescrito no corpo da função antes de ser usado. PlaylistWindow.cpp 89
  • V763 O parâmetro 'rect' é sempre reescrito no corpo da função antes de ser utilizado. ConfigView.cpp 78
  • V763 O parâmetro 'm' é sempre reescrito no corpo da função antes de ser usado. mkntfs.c 3917
  • O parâmetro V763 'rxchainmask' é sempre reescrito no corpo da função antes de ser usado. ar5416_cal.c 463
  • V763 O parâmetro 'c' é sempre reescrito no corpo da função antes de ser usado. if_iwn.c 6854

Conclusão


O projeto Haiku é uma fonte de bugs interessantes e raros. Reabastecemos nosso banco de dados de exemplos de erros e corrigimos vários problemas no analisador identificado durante a análise de código.

Se você não verifica seu código com nenhuma ferramenta de análise de código há muito tempo, provavelmente algo do descrito também está no seu código. Use o PVS-Studio em seu projeto para controlar a qualidade do código, se ele estiver escrito em C, C ++, C # ou Java. Você pode baixar o analisador sem registro e SMS aqui .

Deseja experimentar o Haiku e tiver alguma dúvida? Os desenvolvedores do Haiku convidam você para o canal de telegrama .



Se você deseja compartilhar este artigo com um público que fala inglês, use o link para a tradução: Svyatoslav Razmyslov. Melhores algoritmos de copiar e colar para C e C ++. Haiku OS Cookbook

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


All Articles