Topic: [Risolto][C-API] Come mai cambia il refcnt in questa parte di codice?  (Letto 652 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline Bakuriu

  • python sapiens sapiens
  • ******
  • Post: 2.267
  • Punti reputazione: 2
  • Katon, Goukakyuu no jutsu!
    • Mostra profilo
    • Jack's Blackboard - Il mio blog
Sono sempre alle prese con questa estensione in C.
Ho scoperto che l'operazione di moltiplicazione di questi miei polinomi a volte provoca un segmentation fault(ma dipende. La stessa identica operazione a volte la dà, altre no).

Aggiungendo un po' di print al codice mi sono accorto che ad un certo punto creo un oggetto, che ha ob_refcnt 1(correttamente), dopodichè vado a riempire un array[senza far riferimento a questo oggetto, o almeno a me pare],e magicamente il refcnt scende a 0.
Ma la cosa migliore è che quando vado a ritorna l'oggetto questo ha di nuovo refcnt 1, senza che io abbia mai fatto un Py_INCREF su di esso(il refcnt a 1 iniziale è dovuto alla chiamata a tp_alloc).

Questa è la porzione di codice che sto esaminando:
[codice=c]
        newpoly = modpoly_nullpoly(Tself->r_modulus, Tself->n_modulus);
        j = newpoly->ob_refcnt;
        printf("after null: ref: %d\n", j);
        for (i=0; i < new_size; i++) {
            tmp_ar[ i ] = Py_BuildValue("i", 0);
        }
        
        newpoly->ob_item = tmp_ar;
        newpoly->ob_size = new_size;
        newpoly->allocated = new_size;
        if (newpoly->ob_refcnt != j) {printf("changed!?!? %d\n", newpoly->ob_refcnt);}
        printf("newpoly-before: ");
        printf("ob_size->%d, allocated->%d, degree->%d ref:%d :: ", newpoly->ob_size, newpoly->allocated, newpoly->ob_refcnt,
                (int)PyNumber_AsSsize_t(newpoly->degree,PyExc_OverflowError));
[/codice]

L'output tipo eseguendo il codice:
[codice]null: ref1   #controllo che dopo la creazione abbia refcnt = 1
after null: ref: 1
newpoly-before: ob_size->3, allocated->3, degree->1 ref:0 :: 0, 0, 0,     #notare ref:0[/codice]
Tra parentesi non capisco come mai non stampi il "changed!?!?", visto che j contiene 1 mentre newpoly->ob_refcnt è a 0.

Qualcuno ha qualche idea di dove può essere l'errore?
Ho già perso parecchio tempo nel cercare un qualche bug ma a me sembra non fare DECREF di troppo, e anche l'accesso agli array mi pare gestito correttamente.
« Ultima modifica: Settembre 16, 2012, 21:51 da Bakuriu »

Offline Markon

  • python sapiens sapiens
  • *
  • moderatore
  • Post: 4.104
  • Punti reputazione: 5
    • Mostra profilo
    • Neolithic
Re: [C-API] Come mai cambia il refcnt in questa parte di codice?
« Risposta #1 il: Agosto 13, 2012, 11:24 »
Mmmm...
printf("ob_size->%d, allocated->%d, degree->%d ref:%d :: ", newpoly->ob_size, newpoly->allocated, newpoly->ob_refcnt,  
                (int)PyNumber_AsSsize_t(newpoly->degree,PyExc_OverflowError));  

Il primo argomento da stampare è ob_size, il secondo è allocated, il terzo ob_refcnt.

 ob_size->3, allocated->3, degree->1

E' 1, solo che tu l'hai chiamato degree, no?

Offline Bakuriu

  • python sapiens sapiens
  • ******
  • Post: 2.267
  • Punti reputazione: 2
  • Katon, Goukakyuu no jutsu!
    • Mostra profilo
    • Jack's Blackboard - Il mio blog
Re: [C-API] Come mai cambia il refcnt in questa parte di codice?
« Risposta #2 il: Agosto 13, 2012, 14:05 »
Mmmm...
printf("ob_size->%d, allocated->%d, degree->%d ref:%d :: ", newpoly->ob_size, newpoly->allocated, newpoly->ob_refcnt,  
                (int)PyNumber_AsSsize_t(newpoly->degree,PyExc_OverflowError));  

Il primo argomento da stampare è ob_size, il secondo è allocated, il terzo ob_refcnt.

 ob_size->3, allocated->3, degree->1

E' 1, solo che tu l'hai chiamato degree, no?
ah giusto... mi sembrava fosse impossibile. E che ho aggiunto la stampa di refcnt dopo, ed evidentemente l'ho messa nel posto sbagliato.
A questo punto cercherò di debuggare la parte di codice seguente, perchè lì mi pare che sia tutto in regola.

edit:
Alla fine ho scoperto che in una parte di codice poco più avanti facevo un Py_DECREF di troppo, e inoltre in un'altra funzione usavo realloc e assumevo che realloc impostasse a NULL la nuova memoria.
« Ultima modifica: Agosto 14, 2012, 10:59 da Bakuriu »

Offline Markon

  • python sapiens sapiens
  • *
  • moderatore
  • Post: 4.104
  • Punti reputazione: 5
    • Mostra profilo
    • Neolithic
ehehe bisogna stare attenti ai decrementi e incrementi del refcounter  :)
non dare per scontato nulla sulla memoria quando programmi in C! L'unica cosa a cui puoi stare meno attento sono le variabili locali. Non appena usi un malloc, calloc  e tutto il resto devi ricordare che c'è un segnalino lì  :party: