[C++] Segmentation fault con unordered_map

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
TommyB1992
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 839
Iscrizione: domenica 7 luglio 2013, 15:55
Desktop: GNU/Linux
Distribuzione: Ubuntu 22.04.2 LTS
Sesso: Maschile

[C++] Segmentation fault con unordered_map

Messaggio da TommyB1992 »

Codice: Seleziona tutto

using ClusterMap = std::unordered_map<std::string, Clusters*>;
ClusterMap clusters;

[...]

    bool clusterExists(std::string& clusterName) {
        bool exists;
        #pragma omp critical
        {
            std::cout << "aaa-" << clusterName << "-\n";
            exists = clusters.find(clusterName) != clusters.end();
            std::cout << "bbb\n";
        }

        std::cout << "ccc\n";
        return exists;
    }
    
 
Crasha sempre sul primo std::cout.
La funzione non ha problemi per centinaia di iterazioni e stampando il nome del cluster da controllare non "ci sono caratteri strani" che potrebbero dare errore.

Codice: Seleziona tutto

aaa-f_0.24_6,X1-
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2792
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: [C++] Segmentation fault con unordered_map

Messaggio da DoctorStrange »

Il frammento che hai postato è incompleto. Non si vede come implementi la funzione che lo chiama. Il tuo cout vorrebbe accedere al contenuto di un puntatore (tramite operatore di dereferenziazione "&") però non fai alcun controllo preliminare che il puntatore esista, e quindi anche il suo contenuto. Prova ad anticipare quella specifica cout con un controllo che il puntatore interessato esista, e non sia null, vedi se in questo modo fixi il problema.

Saluti.
TommyB1992
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 839
Iscrizione: domenica 7 luglio 2013, 15:55
Desktop: GNU/Linux
Distribuzione: Ubuntu 22.04.2 LTS
Sesso: Maschile

Re: [C++] Segmentation fault con unordered_map

Messaggio da TommyB1992 »

DoctorStrange ha scritto:
martedì 19 settembre 2023, 14:55
Il frammento che hai postato è incompleto. Non si vede come implementi la funzione che lo chiama. Il tuo cout vorrebbe accedere al contenuto di un puntatore (tramite operatore di dereferenziazione "&") però non fai alcun controllo preliminare che il puntatore esista, e quindi anche il suo contenuto. Prova ad anticipare quella specifica cout con un controllo che il puntatore interessato esista, e non sia null, vedi se in questo modo fixi il problema.

Saluti.
così?

Codice: Seleziona tutto

Clusters* getCluster(AI::Env& environment, ClustersT& clustersList) {
    std::string info_set {getClusterName(environment, clustersList)};
    std::cout << "info_set: " << info_set << "\n";
    if (!clusterExists(info_set)) {
        auto options {environment.getOptions()};
        #pragma omp critical
        {
            clusters.insert({info_set, new Clusters {options}});
        }
    }

    return clusters[info_set];
}
Stampa la stessa cosa che "aaa-xxx-" all'interno di "clusterExists".
Ultima modifica di TommyB1992 il martedì 19 settembre 2023, 15:42, modificato 1 volta in totale.
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2792
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: [C++] Segmentation fault con unordered_map

Messaggio da DoctorStrange »

Il motivo per il quale ti ho chiesto del metodo che chiama questa funzione, è dovuto al fatto che io sospetto che il problema si trovi nella funzione chiamante, e non in questo specifico metodo. Se guardi la firma di questo metodo:

Codice: Seleziona tutto

Clusters* getCluster(AI::Env& environment, ClustersT& clustersList) {
Usi, proprio nella firma, sia puntatori "*" che operatori di dereferenziazione "&". Se questo metodo viene chiamato da una procedura che gli passa valori errati, probabilmente potrebbe essere il motivo dell'errore. Il controllo non lo devi fare in questa funzione, ma in quella chiamante. Nella funzione chiamante controllerai che il puntatore che stai per passare a questo metodo esista, e se esiste, e non è vuoto o "null", allora e solo allora chiamerai questo metodo.
TommyB1992
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 839
Iscrizione: domenica 7 luglio 2013, 15:55
Desktop: GNU/Linux
Distribuzione: Ubuntu 22.04.2 LTS
Sesso: Maschile

Re: [C++] Segmentation fault con unordered_map

Messaggio da TommyB1992 »

Se fosse vero quello che dici però non credo che riuscirebbe a stamparmi "std::cout << "info_set: " << info_set << "\n".
Perchè sono classi che "generano" in runtime il nome del cluster che è assegnato a "info_set", se una delle due fosse errata o null, non generebbe nulla e io non vedrei un valore simile a "f_0.24_6,X1" che viene invece correttamente generato.

Oltretutto il problema si propone solo se carico le informazioni in memoria (che sono molti gb) tramite file che utilizzo come restore dei checkpoints:

Codice: Seleziona tutto

void load_strategy(std::string fileName) {
    std::ifstream f(fileName);
    json j = json::parse(f);

    for (json::iterator it = j.begin(); it != j.end(); ++it) {
        [...]
        clusters.insert({is, new Clusters {options}});
        [...]
    }
}
Se commento la riga:

Codice: Seleziona tutto

// load_strategy("nomefile.json");
Non avrò nessun problema.
Avatar utente
DoctorStrange
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2792
Iscrizione: mercoledì 14 ottobre 2015, 9:33
Desktop: Gnome3
Distribuzione: Ubuntu 22.04 LTS Jammy Jellyfish
Sesso: Maschile
Località: Roma, Italia

Re: [C++] Segmentation fault con unordered_map

Messaggio da DoctorStrange »

Ma il contesto che tu passi è una lista. Ti domando: sei certo che in quella specifica lista non siano ammessi anche valori "null"? In questo caso, i null solleverebbero il tuo errore, mentre la lista rimarrebbe idonea. Di questo però non sono sicuro. Non ricordo molto bene la sintassi del C, se i valori null sono ammessi in quel contesto specifico.
TommyB1992
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 839
Iscrizione: domenica 7 luglio 2013, 15:55
Desktop: GNU/Linux
Distribuzione: Ubuntu 22.04.2 LTS
Sesso: Maschile

Re: [C++] Segmentation fault con unordered_map

Messaggio da TommyB1992 »

DoctorStrange ha scritto:
martedì 19 settembre 2023, 16:22
Ma il contesto che tu passi è una lista. Ti domando: sei certo che in quella specifica lista non siano ammessi anche valori "null"? In questo caso, i null solleverebbero il tuo errore, mentre la lista rimarrebbe idonea. Di questo però non sono sicuro. Non ricordo molto bene la sintassi del C, se i valori null sono ammessi in quel contesto specifico.
No io passo una stringa e poi controllo in una "dizionario" (unordered_map) se la stringa (chiave) è presente.

E l'equivalente in python di if "miachiave" in dizionario dove il dizionario contiene dei puntatori.

Comunque ho fatto una prova, sia cancellando l'oggetto, sia assegnandolo null, e non causa la segmentazione del codice.

Codice: Seleziona tutto

// Online C++ compiler to run C++ program online
#include <iostream>
#include <unordered_map>

class Cluster {};

using ClusterMap = std::unordered_map<std::string, Cluster*>;
ClusterMap clusters;

int main() {
    Cluster* tmp {new Cluster};
    
    clusters["key"] = new Cluster;
    clusters["null"] = nullptr;
    clusters["deleted"] = tmp;
    
    delete tmp; // qui lo cancello nel caso sia questo il problema che non viene creato o viene creato male
    
    if ( clusters.find("key") != clusters.end() ) {
        std::cout << "trovo\n";
    }

    if ( clusters.find("null") != clusters.end() ) {
        std::cout << "trovo\n";
    }
    
    if ( clusters.find("deleted") != clusters.end() ) {
        std::cout << "trovo\n";
    }
    
    delete clusters["key"];
    return 0;
}
L'output è:

Codice: Seleziona tutto

trovo
trovo
trovo
TommyB1992
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 839
Iscrizione: domenica 7 luglio 2013, 15:55
Desktop: GNU/Linux
Distribuzione: Ubuntu 22.04.2 LTS
Sesso: Maschile

Re: [C++] Segmentation fault con unordered_map

Messaggio da TommyB1992 »

Dopo essere impazzito ore, penso che il problema dipenda dalla libreria `nlohmann/json.hpp`

In questo pezzo di codice:

Codice: Seleziona tutto

void load_strategy(std::string fileName) {
    std::ifstream f(fileName);
    // riga 123
    json j = json::parse(f);
    // riga 987
   [...]
}
se metto il return, subito dopo json j = json::parse(f); al posto della riga 987, mi darà SEMPRE un Segmentation fault dopo X iterazioni del mio codice.
Se metto il return PRIMA di quella riga, cioè al posto di 123, il codice non crasherà mai.

È una questione di memoria? Mi sembra piuttosto strano.
Avatar utente
Actarus5
Prode Principiante
Messaggi: 216
Iscrizione: mercoledì 3 luglio 2013, 17:15
Desktop: Mate
Distribuzione: Fedora
Località: Abutalabashuneba

Re: [C++] Segmentation fault con unordered_map

Messaggio da Actarus5 »

Ha senso provare con un try catch allora, in questo modo, però non conosco la libreria in questione, ho solo letto velocemente qualcosa su github:

Codice: Seleziona tutto

try {
	json::parse(f);
}
catch (json::parse_error& e) {
	std::cout << "message: " << e.what() << '\n'
			  << "exception id: " << e.id << '\n'
}
"An extremely helpful console message: “SPANK! SPANK! SPANK! Naughty programmer!”. Really, I’m not joking about that one."
TommyB1992
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 839
Iscrizione: domenica 7 luglio 2013, 15:55
Desktop: GNU/Linux
Distribuzione: Ubuntu 22.04.2 LTS
Sesso: Maschile

Re: [C++] Segmentation fault con unordered_map

Messaggio da TommyB1992 »

Actarus5 ha scritto:
venerdì 22 settembre 2023, 5:15
Ha senso provare con un try catch allora, in questo modo, però non conosco la libreria in questione, ho solo letto velocemente qualcosa su github:

Codice: Seleziona tutto

try {
	json::parse(f);
}
catch (json::parse_error& e) {
	std::cout << "message: " << e.what() << '\n'
			  << "exception id: " << e.id << '\n'
}
il problema è che non crasha li, crasha dopo X iterazioni (è un ciclo for). Il codice fa questo:

1. Carica il Json con una lista
2. Cicla la lista processata con la libreria json e inserisce le sue informazioni in dentro un ordered_map
3. Un ciclo for comincia a "generare" dei dati e se quel dato NON è presente nell'unordered map, lo inserisce, altrimenti lo aggiorna e qui crasha (non c'è un numero di iterazioni, a volte lo fa dopo 100.000 altre dopo 200.000)

Il tutto crasha quando fa il controllo con "clusterExists".
Ho notato due comportamenti:
- Se io metto il return prima del json::parse, non "pre-caricherà" nessun elemento nella mappa, il risultato sarà che il codice non avrà mai nessun problema
- Ho provato a inserire UN solo elemento processato dal json (sono 3gb di dati altrimenti), verificare se l'accoppiata "chiave/valore" abbia problemi, e non ha nessuno (posso accedere, modificare, leggere, verificare se la chiave esiste, etc..., etc...), ma anche in questo caso, se poi avvio il codice, questo crasherà dopo X iterazioni del ciclo for del punto 3

Magari crashasse direttamente sul json::parse, non starei impazzendo così altrimenti
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
Messaggi: 8224
Iscrizione: martedì 30 ottobre 2007, 6:33
Desktop: LXDE
Distribuzione: Ubuntu 18.04.1 LTS
Sesso: Maschile
Località: TO
Contatti:

Re: [C++] Segmentation fault con unordered_map

Messaggio da crap0101 »

stai usando questa?

esclundendo possibilmente bug della lib, il try/catch lo metterei dove fai l' insert() che se non ho capito male è dove - a un certo punto - arrivano i problemi.
Poi, visto il #pragma escuderei problemi di thread :-D ma potrebbe esserci qualche puntatore "spuntato" che vaga lì in giro.
Un run col debugger che dice?
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
TommyB1992
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 839
Iscrizione: domenica 7 luglio 2013, 15:55
Desktop: GNU/Linux
Distribuzione: Ubuntu 22.04.2 LTS
Sesso: Maschile

Re: [C++] Segmentation fault con unordered_map

Messaggio da TommyB1992 »

crap0101 ha scritto:
sabato 23 settembre 2023, 22:24
stai usando questa?

esclundendo possibilmente bug della lib, il try/catch lo metterei dove fai l' insert() che se non ho capito male è dove - a un certo punto - arrivano i problemi.
Poi, visto il #pragma escuderei problemi di thread :-D ma potrebbe esserci qualche puntatore "spuntato" che vaga lì in giro.
Provato ma nulla :/ Alla fine ho fatto una cosa: ho scritto una mia classe per l'IO e ho smesso di salvare i dati in .json.
"Ho risolto", ma perdendo una giornata e mezza.
crap0101 ha scritto:
sabato 23 settembre 2023, 22:24
Un run col debugger che dice?
Intendi con il parametro -ggdb? Così almeno mi regolo per la prossima volta
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: dmcgianluca e 2 ospiti