Errore 6 Overflow Assurdo

di il
16 risposte

Errore 6 Overflow Assurdo

Ancora e non è la prima volta che mi capita ... non capisco

value è un Long 

value = 256 * 233 + 242 mi da errore Overflow ? farebbe 59890

l' errore viene visualizzato sull' istruzione

value = 256 * arr(r * 2 + 1) + arr(r * 2 + 2) e i valori presenti nell due celle sono rispettivamente 233 e 242

non dico balle da immediata

print arr(7)
233 
print arr(8)
242 
print r

Private Sub Leggi_Click()
Dim buffer As Variant
Dim arr() As Byte
Dim setpoint(12) As Byte
Dim value As Long

Call modbus2(255, 3, 0, 18, 0, 6)

Lenght = 6 * 2 + 5
Form1.MSComm2.InputLen = Lenght
While Form1.MSComm2.InBufferCount < Lenght
Wend

buffer = Form1.MSComm2.Input
arr = buffer

For x = 1 To Lenght
    bufrc2(x - 1) = arr(x - 1)
Next x

mycrc = calccrc2(Lenght, 1)

crcl = arr(Lenght - 2)
crch = arr(Lenght - 1)

node = arr(0)
func = arr(1)
btor = arr(2)

If ((crcl = crcl2) And (crch = crch2)) Then
    For r = 1 To btor / 2
        value = 256 * arr(r * 2 + 1) + arr(r * 2 + 2)
        setpoint((r - 1) * 2) = arr(r * 2 + 1)
        setpoint((r - 1) * 2 + 1) = arr(r * 2 + 2)
        BCSETPOINT(r) = value
        Me.Text1(r - 1).Text = Format(BCSETPOINT(r), "00000")
    Next r
Else
    response = MsgBox("MODBUS CRC16 ERROR", vbOKOnly)
    Me.Salva.Enabled = False
    Me.Scrivi.Enabled = False
End If

mycrc = calccrc(10, setpoint())

If mycrc <> BCSETPOINT(6) Then
    response = MsgBox("SETPOINT CRC16 ERROR", vbOKOnly)
    Me.Salva.Enabled = False
    Me.Scrivi.Enabled = False
Else
    response = MsgBox("SETPOINT CRC16 OK", vbOKOnly)
    Me.Salva.Enabled = True
    Me.Scrivi.Enabled = True
End If

End Sub

16 Risposte

  • Re: Errore 6 Overflow Assurdo

    Caro @Numero5, mi sa che il fulmine ti ha ha dato l'intelligenza MA ti ha fritto la ALU (Arithmetic Logic Unit) :-)

    Corto circuito 1986, bellissimo, scemo ma bellissimo! Bei ricordi (e si, ogni tanto me lo riguardo :-))

    A parte i ricordi, OVVIAMENTE NON E' assurdo.

    'value' e' di tipo Long (32 bit, NON 64 bit), 

    NON 

    256 * 233 + 242

    che e' di tipo Integer (16 bit).

    Inoltre, 1 bit serve per il segno, quindi ci sono SOLO 15bit disponibili per il valore.

    Con 15bit il valore massimo e' 32767

    MA

    il risultato di

    256 * 233 + 242

    e' 59890 

    MAGGIORE di 32867

    da cui l'overflow

    Scrivi 

    256L * 233L + 242L

    o comunque usa <costante>L per assicurarti che tutte le parti dell'espressione siano di tipo Long.

    arr e' un array di byte NON di Long, penso che byte sia convertito in Integer oppure addirittura mantenuto in Byte.

  • Re: Errore 6 Overflow Assurdo

    Ciao migliorabile 

    Numero5 é vivo ! Ho cambiato l' Avatar come puoi vedere.

    Long
    (intero lungo)
    4 byteDa -2.147.483.648 a 2.147.483.6477

    Da help di VB6

    quindi per me non ha senso che assegnare ad una variabile long un valore che calcolato e inferiore a 65535 dia un errore di overflow

    sono costretto ad usare Long proprio perchè VB6 non ha variabili Unsigned INT

    ho risolto scrivendola  così

        For r = 1 To btor / 2
            value = 256
            value = value * arr(r * 2 + 1)
            value = value + arr(r * 2 + 2)
            setpoint((r - 1) * 2) = arr(r * 2 + 1)
            setpoint((r - 1) * 2 + 1) = arr(r * 2 + 2)
            BCSETPOINT(r) = value
            Me.Text1(r - 1).Text = Format(BCSETPOINT(r), "00000")
        Next r
  • Re: Errore 6 Overflow Assurdo

    Non hai considerato alcune cose per capire e affrontare la questione.

    Quando VB6 esegue un calcolo, valuta l'espressione a prescindere dalla variabile che sta a sinistra e che conterrà il risultato finale.

    Il VB6 calcola prima

    256 * arr(r * 2 + 1) + arr(r * 2 + 2)

    e usa un'area temporanea per il risultato determinata dal tipo più grande che individua nell'espressione.

    <area temporanea> = <espressione>

    Se tutto va bene, in un secondo momento il VB6 esegue

    variabile = <area temporanea>

    Detto questo per l'espressione di cui parliamo, succede

    <area temporanea> = 256 * arr(r * 2 + 1) + arr(r * 2 + 2)

    e poi

    value = <area temporanea>

    il tipo più grande nell'espressione è il 256 (una costante integer a 2 byte, da -32768 a +32767) e quindi viene preparata un'area temporanea integer,  Ma l'espressione dà un risultato di grandezza Long e quindi non entra nell'area temporanea da cui l'errore. La causa dell'errore è come è stata scritta l'espressione e il tipo di variabile a sinistra non ha alcuna rilevanza.

    Per risolvere devi far creare al VB6 un'area temporanea Long e questo avviene indicando come Long uno dei termini. Nel tuo caso ti conviene intervenire sulla costante 256 indicando che è di tipo Long e tutto va a buon fine. Devi quindi aggiungere il carattere & alla costante perchè sia intesa Long e l'area temporanea sia creata di tipo Long

    Quindi

    value = 256& * arr(r * 2 + 1) + arr(r * 2 + 2)

    Capito?

    P.S. Dato che usi value solo per assegnarlo subito dopo, potresti non utilizzarlo e scrivere direttamente

    BCSETPOINT(r) = 256& * arr(r * 2 + 1) + arr(r * 2 + 2)

  • Re: Errore 6 Overflow Assurdo

    In effetti era spiegato anche qui anche se non mi era chiarissimo cosa intendessero 

    Overflow (errore 6)

    Un overflow può essere il risultato di un'assegnazione superiore al valore massimo previsto. Cause e soluzioni dell'errore:

    • Il risultato di un'assegnazione, di un calcolo o di una conversione del tipo di dati ha dimensioni troppo grandi per poter essere rappresentato nell'intervallo di valori consentito per il tipo specifico di variabile.

      Assegnare il valore ad una variabile associata ad un tipo di dati che accetta intervalli di valori maggiori.

    • Un'assegnazione ad una proprietà supera il valore massimo consentito per la proprietà.

      Assicurarsi che il valore assegnato rientri nell'intervallo consentito per la proprietà.

    • Si è cercato di utilizzare un numero in un calcolo e si è impostato forzatamente il tipo Integer per tale numero, ma il risultato è più grande di un valore Integer. Ad esempio:

      Come se fossi io ad imporre che tipo di variabile utilizzare nel calcolo interno !!!

          Dim x As Long
          x = 2000 * 365   ' Errore: overflow

      Per risolvere il problema, digitare il numero nel seguente modo:

          Dim x As Long
          x = CLng(2000) * 365

      D' altra parte

    • Operatore *
    •       
    • Utilizzato per moltiplicare due numeri.
    • Sintassi
    • risultato = numero1*numero2
    • La sintassi dell'operatore * è composta dalle seguenti parti:
    • ParteDescrizione
      risultatoObbligatoria. Qualsiasi variabile numerica.
      numero1Obbligatoria. Qualsiasi espressione numerica.
      numero2Obbligatoria. Qualsiasi espressione numerica.
    • Osservazioni
    • Il tipo di dati di risultato è in genere quello dell' espressione più precisa. L'ordine di precisione crescente è Byte, Integer, Long, Single, Double, Currency e Decimal. Esistono tuttavia alcune eccezioni a tale tipo di ordine:
    • SeRisultato sarà
      La moltiplicazione viene eseguita tra valori Single e Long,convertito in Double.
      Il tipo di dati di risultato è un valore Variant di tipo Long, Single o Date che non rientra nell'intervallo consentito,convertito in un valore Variant che contiene un valore Double.
      Il tipo di dati di risultato è un valore Variant di tipo Byte che non rientra nell'intervallo consentito,convertito in un valore Variant di tipo Integer.
      Il tipo di dati di risultato è un valore Variant di tipo Integer che non rientra nell'intervallo consentito,convertito in un valore Variant di tipo Long.
    • Se una o entrambe le espressioni sono espressioni Null, risultato sarà Null. Qualsiasi espressione con valore Empty sarà considerata uguale a 0.
    • Nota   L'ordine di precisione utilizzato per la moltiplicazione non è lo stesso utilizzato per l'addizione e la sottrazione.

      Quindi se il risultato viene convertito in un tipo più grande ... VB6 potrebbe convertirsi i valori interni da solo senza dare errore Overflow sul suo calcolo interno ma forse sono io che sbaglio ad insistere nell' utilizzare ancora VB6 anzichè linguaggi più recenti ed aggiornati.

  • Re: Errore 6 Overflow Assurdo

    21/03/2025 - Numero5 ha scritto:

    Quindi se il risultato viene convertito in un tipo più grande ... VB6 potrebbe convertirsi i valori interni da solo senza dare errore

    Le regole sono semplici, basta esserne coscienti, non ci sono situazioni "assurde"

     Overflow sul suo calcolo interno ma forse sono io che sbaglio ad insistere nell' utilizzare ancora VB6 anzichè linguaggi più recenti ed aggiornati.

    Con molti linguaggi hai questo tipo di problemi, anche moderni

  • Re: Errore 6 Overflow Assurdo

    Ciao Oregon

    non voglio essere polemico tutto ciò che dici è vero.

    Ma da un compilatore / interprete di un linguaggio di programmazzione mi aspetterei una logica diversa

    leggo da sx a destra una istruzione 

    ho una variabile long

    a cui devo assegnare i risultato di quello che c'è a destra dell' "=" qualunque cosa ci sia sarà un risultato long

    quindi nell' istruzione value = 256 * 255 + 255 dovrebbe essere implicito che dovrebbe fare i calcoli interni con una Long

    se valuti di usare una INT perchè 256 è INT poi hai un operatore di moltiplicazione X 128 basta per mandarti in overflow in particolare con un signedINT

  • Re: Errore 6 Overflow Assurdo

    21/03/2025 - Numero5 ha scritto:

    Leggo da sx a destra una istruzione 

    Il fatto è che la compilazione/interpretazione delle linee di programma non funziona così.

    In una linea come

    variabile = <espressione>

    per prima cosa viene valutata la parte a destra dell'= ovvero

    <espressione>

    e quindi viene controllata e valutata ricorsivamente l'espressione. Il risultato dell'espressione, man mano che viene valutata, va a finire in un'area temporanea.

    Solo dopo avere ottenuto regolarmente un risultato, viene eseguita la parte

    variabile =

    da cui tutto quello che si è detto.

  • Re: Errore 6 Overflow Assurdo

    @Numero5, a te sembra 'banale', una 'castronata di implementazione', ma tu ragioni SOLO basandoti sul tuo caso specifico.

    Considera che l'espressione che hai usato puo' essere una parte di un'espressione piu' complessa, oppure usata in un contesto in cui NON C'E' nessun tipo di assegnamento.

    Ti assicuro che implementare la tua idea in modo "generale" e', nel caso piu' semplice, "un bagno di sangue e lacrime", se non addirittura "impossibile".

    Ovviamente, va da se che NON SI POSSONO IMPLEMENTARE comportamenti del compilatore/interprete che dipendono da espressioni 'particolari'. Tutto DEVE ESSERE PREVEDIBILE.

    Ti consiglio di studiare come funziona una 'grammatica' usata per definire un linguaggio di programmazione.

    A te sembra 'banale leggere da sx a dx' 

    MA NON LO SI PUO' FARE

    perche' l'assegnamento e' L'ULTIMA espressione da valutare, NON LA PRIMA.

  • Re: Errore 6 Overflow Assurdo

    21/03/2025 - Numero5 ha scritto:

    ho risolto scrivendola  così

        For r = 1 To btor / 2
            value = 256
            value = value * arr(r * 2 + 1)
            value = value + arr(r * 2 + 2)
            setpoint((r - 1) * 2) = arr(r * 2 + 1)
            setpoint((r - 1) * 2 + 1) = arr(r * 2 + 2)
            BCSETPOINT(r) = value
            Me.Text1(r - 1).Text = Format(BCSETPOINT(r), "00000")
        Next r

    value è long quindi i calcoli interni li fa su long e l' errore non me lo da più.

    RIPETO non voglio fare polemica ma capire perchè vado incontro ad errori che non mi aspetto

    ho creato un programmino  una tabellina, ma non sono riuscito a generare l' errore di overflow.

    Private Sub Form_Load()
    
    Call tabellina
    End
    
    End Sub
    
    Sub tabellina()
    Dim tabella As Integer
    Dim x, y As Byte
    
    For x = 1 To 30
        For y = 1 To 10
            tabella = 10 * x * y
            If y = 10 Then
                Debug.Print Format(tabella, "0000") & vbCrLf
            Else
                Debug.Print Format(tabella, "0000") & " ";
            End If
        Next y
    Next x
    
    End Sub
    
    

    tabella = X * y non dava errore, sono tutti byte

    quindi ho provato 

    tabella = 10 * x * y ,sono tutti byte

    ma neanche questo da errore

    se non riesco a generare l' errore di overflow non mi convinco. Come posso generare l' Errore ?

  • Re: Errore 6 Overflow Assurdo

    21/03/2025 - Numero5 ha scritto:

    RIPETO non voglio fare polemica ma capire perchè vado incontro ad errori che non mi aspetto

    Questo si è capito, nessuno vuole fare polemica.

    Questi errori non te li aspetti semplicemente perché non conosci a fondo il funzionamento dei compilatori/interpreti, nulla di strano.

    Un'altra cosa che non sai (e questa è una caratteristica del VBA, non stai usando il C) è che se scrivi

    Dim x, y As Byte

    è come se scrivessi

    Dim x As Variant, y As Byte

    e che per renderli tutti e due come Byte devi scrivere

    Dim x As Byte, y As Byte

    Nell'espressione devi espressamente indicare che la costante 10 sia un byte per avere un errore, altrimenti viene intesa come Integer a 2 byte (di default).

    Quindi

    tabella = CByte(10) * x * y

  • Re: Errore 6 Overflow Assurdo

    Ve bene essere come "San Tommaso: non ci credo fino a che non ci metto il naso",

    MA l'  "Informatica" e' come la "matematica", NON come la "lotteria" ;-)

    Per capire come funziona SI STUDIA, NON SI VA A TENTATIVI ;-)

    Comunque: loop da 0 a 255 , NON da 0 a 10 o 30

    10 * x * y  con x = 30 e y = 10, l'espressione vale 3000 (TREMILA) ABBONDANTEMENTE MENO DI 32767 (TRENTADUEMILA e spiccioli)

    Ed e' pure MENO di 3000, visto che x massimo e' 29 e y massimo e' 9

  • Re: Errore 6 Overflow Assurdo

    Effettivamente Oregon ha ragione

    Sub tabellina()
    Dim tabella As Integer
    Dim x As Byte
    Dim y As Byte
    
    For x = 1 To 30
        For y = 1 To 10
            tabella = CByte(10) * x * y
            If y = 10 Then
                Debug.Print Format(tabella, "0000") & vbCrLf
            Else
                Debug.Print Format(tabella, "0000") & " ";
            End If
        Next y
    Next x
    
    End Sub

    immediata

    0010 0020 0030 0040 0050 0060 0070 0080 0090 0100
    
    0020 0040 0060 0080 0100 0120 0140 0160 0180 0200
    
    0030 0060 0090 0120 0150 0180 0210 0240 
    
    print x,y
     3             9 
    

    al contrario

    Sub tabellina()
    Dim tabella As Integer
    Dim x As Byte
    Dim y As Byte
    
    For x = 1 To 30
        For y = 1 To 10
            tabella = 1000 * x * y
            If y = 10 Then
                Debug.Print Format(tabella, "00000") & vbCrLf
            Else
                Debug.Print Format(tabella, "00000") & " ";
            End If
        Next y
    Next x
    
    End Sub

    immediata

    01000 02000 03000 04000 05000 06000 07000 08000 09000 10000
    
    02000 04000 06000 08000 10000 12000 14000 16000 18000 20000
    
    03000 06000 09000 12000 15000 18000 21000 24000 27000 30000
    
    04000 08000 12000 16000 20000 24000 28000 32000 
    
    print x,y
     4             9 

    qui l' overflow è dovuto al superamento del Integer di tabella

    san tommaso è soddisfatto

  • Re: Errore 6 Overflow Assurdo

    21/03/2025 - Numero5 ha scritto:

    qui l' overflow è dovuto al superamento del Integer di tabella

    No, la variabile tabella il VBA ancora ignora di che tipo sia quando c'è l'errore. Questo è dovuto al superamento della capacità assegnata alla <area temporanea> usata per il calcolo dell'espressione.

    Fai ancora lo stesso errore  che ti ha portato  questa discussione.

  • Re: Errore 6 Overflow Assurdo

    Vero ancora hai ragione camiando la tabella in long l' errore avviene nello stesso momento

    e ho risolto come al solito assegnando il valore più grande a Long tabella

    Direi di finirla qui

    Dovrei aprire una nuova discussione per un nuovo argomento, e probabilmente lo farò 

    ma io uso i long perchè non ho a disposizione unsigned int ma a volte il valore di un registro modbus è negativo

    e in quel caso ho bisogno di convertire il long in signed int ma non credo che sia possibile se ricordo bene da un errore di overflow

    cosa potrei fare ? passare per una stringa ? altre idee ?

    Sub tabellina()
    Dim tabella As Long
    Dim x As Byte
    Dim y As Byte
    
    For x = 1 To 30
        For y = 1 To 10
            tabella = 1000
            tabella = tabella * x * y
            If y = 10 Then
                Debug.Print Format(tabella, "000000") & vbCrLf
            Else
                Debug.Print Format(tabella, "000000") & " ";
            End If
        Next y
    Next x
    
    End Sub
    
Devi accedere o registrarti per scrivere nel forum
16 risposte