+ Rispondi al Thread
Pagina 1 di 2 12 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 14

Discussione: Advanced troubleshooting per errori memoria

  1. #1
    Hyde non è in linea Scolaretto
    Luogo
    Roma
    Post
    325

    Advanced troubleshooting per errori memoria

    Salve a tutti,
    vi espongo la mia situazione in cerca di validi spunti.

    Ho un progetto decisamente corposo basato su MFC. Nel codice ho alcune classi "contenitori" che mi archiviano in memoria una serie di dati che uso di frequente all'interno del codice e che sono fisicamente residenti su un db. Ho implementato questi contenitori come singleton in modo da poterle usare in tutto il codice evitando di dichiararli come membri pubblici della mia app.
    Il popolamento di questi contenitori avviene su un thread separato (che ha la sua proprio connessione al db) mentre l'utente effettua il login (guadagno tempo).

    Tutto bene, fino a che non decido di fare un po' di refactoring del codice: niente di che, spostamento di alcune variabili, creazioni di helper specifici etc.
    Da questo momento in poi ho un comportamento che non riesco a spiegarmi: in una routine ben precisa di uno di questi contenitori, la memoria viene cancellata mentre sto assegnando i valori ai suoi membri cusandomi quindi una violazione di accesso. Il fenomeno si è verificato su diversi contenitori di questo tipo e man mano sono riuscito a spostare sempre più nell'ipotetica sequenza di popolamento l'errore semplicemente riallineando i membri di queste classi (miglior padding e conseguentemente minor grandezza in byte della classe).

    Per rendere l'idea dell'errore cerco di farvi un esempio:

    codice:
    class Singleton
    public:
    static Singleton& Get();
    bool LoadData(CDatabase* db);
    protected:
    	Singleton();
    	static Singleton* m_smpManager;
    	static void Init();
    
    	myStruct m_arrSCache[200];
    Ora nell'init inizializzo la mia struttura, poi il thread secondario chiama il LoadData passandogli il db e la funzione dovrebbe popolare l'array con i giusti dati.
    Debugger alla mano questo è ciò che osservo:
    1. Dopo la Init, la struttura è correttamente inizializzata
    2. in entrata nella routine LoadData la struttura ha ancora i miei valori di inizializzazione
    3. appena nella funzione comincio a allocare spazio per variabili e/oggetti, vedo che i valori dell'array cominciano a "sporcarsi"
    4. alla fine la struttura è compromessa ed al primo assegnamento: crash

    Ipotizzo sia un problema di spazio (anche se non me lo spiego).
    Qualche idea su come tracciare e risolvere il problema?

    P.S.
    Non ci sono altri thread che fanno chiamate a quei contenitori durante la fase di inizializzazione, o almeno così dovrebbe essere.

  2. #2
    L'avatar di AntonioG
    AntonioG non è in linea Moderatore Globale Ultimo blog: Commodore 64 e Codemotion
    Luogo
    Roma
    Post
    15,210
    Blogs
    5
    Ci dovresti mostrare il codice della Init e soprattutto della LoadData
    Avvisi generali e importanti, a pena CHIUSURA thread e/o BAN
    Il crossposting è vietato.
    Le richieste di "pappa pronta" sono vietate.
    Utilizzate i tag CODE per il codice.
    Leggere il Regolamento per chiarimenti PRIMA di creare nuovi thread.
    Utilizzare sempre i PM per comunicare con i moderatori.
    Non mi contattate in PM per problemi di software, usate il forum

  3. #3
    L'avatar di Bemipefe
    Bemipefe non è in linea Scolaretto
    Luogo
    Italy
    Post
    177
    Purtroppo in questi casi non c'è una soluzione ma una strategia.
    L'unica cosa sicura è c'è un memory violation da qualche parte.
    La cosa utile da capire è se questo è generato dal tuo codice o da librerie che stai usando.
    Non è detto che sia la classe stessa ad avere il problema ...potrebbe essere un altro pezzo di codice di un altra classe che va a corrompere quella zona di memoria relativa al Singleton.

    Devi partire dall'alto e provare a commentare delle parti di codice. Quando hai capito la parte di codice che fa generare il problema ti concentri su quella. Altrimenti devi utilizzare degli strumenti per rilevare questo tipo di problemi ma non sempre è facile farli funzionare e non sempre danno informazioni utili. Ti allego qualche link di partenza:

    https://msdn.microsoft.com/en-us/library/6decc55h.aspx
    https://msdn.microsoft.com/en-us/library/w500y392.aspx

    Spesso anche rileggere il codice aiuta.
    Se usi i thread potrebbero esserci delle race condition o dei problemi di sincronizzazione.

    Buona fortuna
    _/\/\/\Bemipefe/\/\/\_

  4. #4
    Hyde non è in linea Scolaretto
    Luogo
    Roma
    Post
    325
    Intanto grazie ad entrambi.

    Purtroppo @AntonioG non credo sia una questione di Load.. Come scritto, infatti, ciò che ora mi si verifica su un contenitore, fino ad oggi pomeriggio si verificava su un altro e prima su una altro ancora. Le routine di load sono veramente banali (apro un recordset e popolo).

    Qualcosa sta sporcando la memoria. So benissimo che problemi di questo tipo non si risolvono su un forum, ma magari qui ci si scambiano strategie per risolverli, o semplicemente parlarne ti fa accendere la lampadina, come spesso mi è successo.

    Ora, la mia ipotesi è che la memoria la stia sporcando il thread stesso.
    Mostro uno spaccato della mia Load, così parliamo del caso reale

    codice:
    bool LoadData(CDatabase* db)
    {
    myComplexObject ccr;
    	int capsN = 0;
    
    	try
    	{
    		// già c'è questa posizione
    
    		CRecordSet rsSTD((db));
    		
    		rsSTD.Open();
    
    		while(!rsSTD.IsEOF())
    		{
    			if (theApp.m_testContainer.GetMeTheRecord(rsSTD.m_id, &ccr))  // ancora non lo trasformo in Singleton e visto i problemi, non so se lo farò :)
    			{
    				capsN = rsSTD.m_Number;
    				if (IsValidPos(capsN))
    				{
    					arrSCache[capsN].m_pType = tpw_std;
    					arrSCache[capsN].m_barcode = (rsSTD.m_stdValue > 0) ? ccr.m_CaliblLot : _T("Empty");
    					arrSCache[capsN].m_idRapDil = rsSTD.m_concentration;
    					arrSCache[capsN].m_expDate = ccr.m_ExpDate;
    				}
    			}
    
    			rsSTD.MoveNext();
    		}
    
    		rsSTD.Close();		
    	}
    catch(CDBException* e)
    {
    blah bla
    }
    
    }
    In entrata arrSCache è ben inizializzato. Già alla prima allocazione con la dichiarazione di myComplexObject, arrSCache comincia parzialmente a sporcarsi. Da qui ne ho dedotto che sia il thread stesso a sporcare..

    Cerco di trarre spunto dai link che mi avete proposto, ogni altra idea è ben accetta.

  5. #5
    L'avatar di AntonioG
    AntonioG non è in linea Moderatore Globale Ultimo blog: Commodore 64 e Codemotion
    Luogo
    Roma
    Post
    15,210
    Blogs
    5
    Puoi mostrare il costruttore di

    myComplexObject

    ?
    Avvisi generali e importanti, a pena CHIUSURA thread e/o BAN
    Il crossposting è vietato.
    Le richieste di "pappa pronta" sono vietate.
    Utilizzate i tag CODE per il codice.
    Leggere il Regolamento per chiarimenti PRIMA di creare nuovi thread.
    Utilizzare sempre i PM per comunicare con i moderatori.
    Non mi contattate in PM per problemi di software, usate il forum

  6. #6
    Hyde non è in linea Scolaretto
    Luogo
    Roma
    Post
    325
    codice:
    myComplexObject ::myComplexObject ()
    {
    	m_idFactor			= 0;
    	m_factor			= 0.0;
    	
    	for(int x = 0; x < MAX_POS;++x)
    	{
    		m_stds[x].m_stdPosition = 0;
    		m_stds[x].m_stdConcentration = 1;
    		m_stds[x].m_stdValue	= float();
    		m_stds[x].m_stdOd		= double();
    		m_stds[x].m_stdOdBlank = double();
    		m_stds[x].m_stdValueCalc	= float();
    		m_stds[x].m_usedInCalc		= true;
    	}
    
    
    	m_CalibMode			= 0;
    	m_CaliblLot			= _T("lot");
    	m_CalibExpDate		= _T("YYYY/MM");
    	m_IdMethod			= 0;
    	m_nStd				= 0;
    	m_factorMin			= 0.0;
    	m_factorMax			= 0.0;
    	m_stdNTest			= 1;
    	m_calStab			= 0;
    	m_outOfSTD			= FALSE;
    }

  7. #7
    L'avatar di AntonioG
    AntonioG non è in linea Moderatore Globale Ultimo blog: Commodore 64 e Codemotion
    Luogo
    Roma
    Post
    15,210
    Blogs
    5
    Si può vedere tutta la classe myComplexObject ?

    In particolare, cosa è m_stds ?
    Avvisi generali e importanti, a pena CHIUSURA thread e/o BAN
    Il crossposting è vietato.
    Le richieste di "pappa pronta" sono vietate.
    Utilizzate i tag CODE per il codice.
    Leggere il Regolamento per chiarimenti PRIMA di creare nuovi thread.
    Utilizzare sempre i PM per comunicare con i moderatori.
    Non mi contattate in PM per problemi di software, usate il forum

  8. #8
    Hyde non è in linea Scolaretto
    Luogo
    Roma
    Post
    325
    m_stds è un array di strutture di tipo StdEntity:

    codice:
    struct StdEntity
    	{
    		long		m_stdConcentration; // puntatore alla tabella dei rapporti di concentrazione
    		float		m_stdOd;
    		float		m_stdOdBlank;
    		float		m_stdValueCalc;
    		short int	m_stdPosition;
    		bool		m_usedInCalc;
    		inline bool		IsOneToOne()
    		{
    			return (m_stdConcentration == 0 || m_stdConcentration == 1);
    		};
    		inline bool IsPoint0()
    		{
    			return (m_stdValue == 0.0);
    		};
    
    	};
    
    StdEntity m_stds[MAX_POS];
    Non sta lì il topo, Antonio...

    Dico questo perché man mano che opero cambiamenti, ad esempio, accorpando la dichiarazione di uan classe all'interno del file header del suo manager, invece che su file separati, l'errore si presenta in altri punti e non più in quella stessa routine.

    Se ci fosse qualche problema con il linking, potrebbe manifestarsi anche così?
    Ultima modifica di Hyde; 20-04-2017 09:34 

  9. #9
    L'avatar di Bemipefe
    Bemipefe non è in linea Scolaretto
    Luogo
    Italy
    Post
    177
    Non credo che problemi di linking ti diano crash ...al massimo non ti linka e non ti genera il binario.
    Un altra cosa utile da ricontrollare è lo scope delle variabili. In particolare Object Variables vs Object Pointers.
    Controlla che tutti le Object Variables assegnate come reference (&) non abbiano lo scope nella sola funzione. Non è il caso delle tue m_ ma può capitare di avere una svista.

    Per il resto come ho già detto dovresti far funzionare il software a compertimenti stagni ossia isolando la parte che ti da problemi da altri moduli / librerie che potrebbero essere la causa del problema. Ad esempio nel main potresti commentare tutte le parti che non riguardano il Singleton e man mano decommentarle fino a che non trovi l'istruzione che decommentata ti causa il problema.
    E' molto empirica come soluzione ma spesso funziona.
    _/\/\/\Bemipefe/\/\/\_

  10. #10
    Hyde non è in linea Scolaretto
    Luogo
    Roma
    Post
    325
    Sono andato avanti con la diagnostica facendo una cosa molto semplice: epurando dallo startup dell'app tutto, dai thread alle allocazioni di altre classi etc. in modo che l'applicazione facesse solo ed esclusivamente quella routine. Risultato? Anche commentando tutto ed addirittura commentando il codice eseguito da quella routine, mantenendo solo le due dichiarazioni delle variabili, in uscita dalla funzione ho un errore di stack corrotto.

    Bah..

+ Rispondi al Thread
Pagina 1 di 2 12 ultimoultimo

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi