Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12

Discussione: [C++] memory leaks

  1. #1

    [C++] memory leaks

    Salve,

    credete che il seguente codice 8che mi funziona benissimo) possa portare a dei memory leaks?

    codice:
    #define _CRT_SECURE_NO_WARNINGS
    #include <windows.h>
    #include <vector>
    #include <cstdlib>
    #include <ctime>
    #include <cstdio>
    #include <boost/circular_buffer.hpp>
    using namespace std;
    using namespace boost;
    
    char * getDateTime(void);
    const short numbuff = 5;
    const short buflen  = 30;
    
    typedef struct
    {
    	unsigned char * pData;
    	unsigned short bufferLength;
    	unsigned short bytesRecorded;
    	bool flag;
    } Buffer;
    
    int main()
    {
    	circular_buffer<Buffer*> cb(numbuff);
    	circular_buffer<Buffer*>::const_iterator it;
    
    	// fill buffer
    	for(int i = 0; i<numbuff; i++)
    	{
    		// set up buffer
    		Buffer *buff       = new Buffer;
    		ZeroMemory(buff, sizeof(Buffer));
    
    		buff->bufferLength  = buflen;
    		buff->bytesRecorded = buflen;
    		buff->flag          = true;
    		buff->pData         = new unsigned char[buflen];
    		buff->pData         = reinterpret_cast<unsigned char *>(getDateTime());
    
    		// push buffer
    		cb.push_back(buff);
    
    		Sleep(1000);
    	}
    
    	// show elements
    
    	for(int i = 0; i<(int)cb.size(); i++)
    	{
    		printf("%s\n", cb[i]->pData);
    	}
    
    	system("pause");
    	return EXIT_SUCCESS;
    }
    
    // getDateTime (Fri, 10 Oct 2008 14:41:59 GMT)
    char * getDateTime(void)
    {
    	time_t rawtime;
    	struct tm * timeinfo;
    	time(&rawtime);
    	timeinfo = gmtime(&rawtime);
    	char * buffer = new char[30];
    	strftime(buffer,30,"%a, %d %b %Y %X GMT",timeinfo);
    	return buffer;
    }
    una volta uscito dal primo ciclo non posso fare più delete in quanto buff non esiste più...
    Alla batteria dai retta ballA

  2. #2
    il codice seguente crea un buffer circolare composto da 5 elementi e ne inserisce 10, quindi solo gli ultimi 5 elementi rimangono nell'anello. Il mio dubbio atroce è: i buffer vengono sovrascritti nella locazione di memoria precedente (unsigned char*) oppure in una nuova locazione?

    codice:
    #include <windows.h>
    #include <vector>
    #include <cstdlib>
    #include <ctime>
    #include <cstdio>
    #include <boost/circular_buffer.hpp>
    using namespace std;
    using namespace boost;
    
    char * getDateTime(void);
    const short numbuff = 5;
    const short buflen  = 30;
    
    typedef struct
    {
    	unsigned char * pData;
    	unsigned short bufferLength;
    	unsigned short bytesRecorded;
    	bool flag;
    } Buffer;
    
    int main()
    {
    	circular_buffer<Buffer*> cb(numbuff);
    	circular_buffer<Buffer*>::const_iterator it;
    
    	printf("Push elements:\n");
    	// fill buffer
    	for(int i = 0; i<10; i++)
    	{
    		// set up buffer
    		Buffer *buff       = new Buffer;
    		ZeroMemory(buff, sizeof(Buffer));
    
    		buff->bufferLength  = buflen;
    		buff->bytesRecorded = buflen;
    		buff->flag          = true;
    		buff->pData         = new unsigned char[buflen];
    		buff->pData         = reinterpret_cast<unsigned char *>(getDateTime());
    		
    		printf("%s\n", buff->pData);
    
    		// push buffer
    		cb.push_back(buff);
    
    		Sleep(1000);
    	}
    
    	printf("\nShow elements:\n");
    
    	// show elements
    	for(int i = 0; i<static_cast<int>(cb.size()); i++)
    	{
    		printf("%s\n", cb[i]->pData);
    	}
    
    	system("pause");
    	return EXIT_SUCCESS;
    }
    
    // getDateTime (Fri, 10 Oct 2008 14:41:59 GMT)
    char * getDateTime(void)
    {
        time_t rawtime;
        struct tm timeinfo;
        time(&rawtime);
        gmtime_s(&timeinfo, &rawtime);
        char * buffer = new char[30];
        strftime(buffer, 30, "%a, %d %b %Y %X GMT", &timeinfo);
        return buffer;
    }
    grazie
    Alla batteria dai retta ballA

  3. #3
    Credo che l'unico modo per non avere memory leaks sia la seguente:

    codice:
    #include <windows.h>
    #include <vector>
    #include <cstdlib>
    #include <ctime>
    #include <cstdio>
    #include <cstring>
    #include <boost/circular_buffer.hpp>
    using namespace std;
    using namespace boost;
    
    void getDateTime(char * szTime);
    const int numbuff = 3;
    const int buflen  = 30;
    
    struct Buffer
    {
    public:
    	char payload[4096];
    	int bufferLength;
    	int bytesRecorded;
    	int user;
    	Buffer() : bufferLength(0), bytesRecorded(0), user(0) { }
    };
    
    int main()
    {
    	circular_buffer<Buffer> cb(numbuff);
    
    	// Insert elements
    	printf("Push elements:\n");
    	for(int i = 0; i<5; i++)
    	{
    		// Get time
    		char szTime[30]; getDateTime(szTime);
    
    		// Init Buff
    		Buffer buff;
    		ZeroMemory(&buff, sizeof(Buffer));
    
    		memcpy(static_cast<void*>(buff.payload), szTime, buflen);
    		buff.user          = i;
    		buff.bufferLength  = buflen;
    		buff.bytesRecorded = buflen;
    
    		cb.push_back(buff);
    
    		printf("%s\n", buff.payload);
    		Sleep(1000);
    	}
    
    	// Show elements:
    	printf("Show elements:\n");
    	for(int i = 0; i<(int)cb.size(); i++)
    	{
    		printf("%s\n", cb[i].payload);
    	}
    
    	system("pause");
    	return EXIT_SUCCESS;
    }
    
    void getDateTime(char * szTime)
    {
    	time_t rawtime = time(NULL);
    	struct tm timeinfo;
    	gmtime_s(&timeinfo, &rawtime);
    	strftime(szTime, 30, "%a, %d %b %Y %X GMT", &timeinfo);
    }
    dove char payload[4096] e settato ad un numero grande come 4096, ogni volta il buffer sarà nettamente minore...ma almeno so che posso far affidamento ad un buffer di lunghezza fino a 4096 bytes...userà poi memcpy per copiare dalla sorgente a payload (senza aggiungere null etc...) gli altri campi della struttura mi diranno quanto è veramente lunga la stringa...

    che ne dite??
    Alla batteria dai retta ballA

  4. #4
    approposito, non riesco a capire questa:

    memcpy è una funzione del linguaggio C definita nella libreria standard ANSI C e dichiarata nell'header file string.h. La funzione esegue la copia delle porzioni di memoria a cui si riferiscono i suoi argomenti. La funzione memcpy è implementata per copiare zone di memoria non sovrapposte; se c'è sovrapposizione il comportamento della funzione è indefinito.
    ovvero, cosa significa zone di memoria non sovrapposte
    Alla batteria dai retta ballA

  5. #5
    Vuol dire che non la puoi utilizzare se l'area di memoria di origine e di destinazione in parte si sovrappongono. In quel caso devi usare la memmove.
    Amaro C++, il gusto pieno dell'undefined behavior.

  6. #6
    Originariamente inviato da MItaly
    Vuol dire che non la puoi utilizzare se l'area di memoria di origine e di destinazione in parte si sovrappongono. In quel caso devi usare la memmove.
    tuttociò per me è incomprensibile...si sovrappongono??
    Alla batteria dai retta ballA

  7. #7
    codice:
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    
    int main()
    {
        char stringa[250]="ci sono le mezze stagioni";
        //L'area di memoria di origine e di destinazione si sovrappongono (stringa+4 ad esempio appartiene sia all'origine che alla destinazione) => memmove
        memmove(stringa + 4, stringa, strlen(stringa)+1);
        //L'area di memoria di origine e di destinazione non si sovrappongono => memcpy
        memcpy(stringa, "non ", 4);
        //L'area di memoria di origine e di destinazione si sovrappongono => memmove
        memmove(stringa + 17, stringa + 12, strlen(stringa+12));
        //L'area di memoria di origine e di destinazione non si sovrappongono => memcpy
        memcpy(stringa+12, "piu' ",5);
        std::cout<<stringa<<std::endl;
        return 0;
    }
    Output:
    codice:
    matteo@teoubuntu:~/cpp/test$ g++ -O3 -Wall -Wextra -ansi -pedantic memmove.cpp -o memmove.x
    matteo@teoubuntu:~/cpp/test$ ./memmove.x
    non ci sono piu' le mezze stagioni
    matteo@teoubuntu:~/cpp/test$
    Se invece sostituisci tutte le memmove con memcpy, puoi ottenere risultati errati; sulla mia macchina, ad esempio:
    codice:
    matteo@teoubuntu:~/cpp/test$ g++ -O3 -Wall -Wextra -ansi -pedantic no_memmove.cpp -o no_memmove.x
    matteo@teoubuntu:~/cpp/test$ ./no_memmove.x 
    non ci scio piu' leo llze stagioni
    matteo@teoubuntu:~/cpp/test$
    .
    Questo accade perché la memcpy copia la memoria in maniera semplice, una cosa del tipo:
    codice:
    void * memcpy(void * destination, void * source, size_t num)
    {
        char * write=destination, * read=source;
        while(num-- > 0)
            *write++=*read++;
        return destination;
    }
    per cui, se le aree di memoria si sovrappongono, è possibile che una parte del buffer di input venga sovrascritta prima di essere copiata. La memmove, invece, garantisce che la copia avvenga sempre come se il buffer di input venisse prima copiato in un buffer temporaneo. All'atto pratico poi nessuna memmove farà così, ma copierà in un verso piuttosto che nell'altro in base alla posizione reciproca delle due aree di memoria.
    Amaro C++, il gusto pieno dell'undefined behavior.

  8. #8
    Ok, perfetto. Volevo chiederti solo un'ultima cosa...ho una stringa (array di caratteri) che ha lunghezza fissa:

    codice:
    struct Buffer
    {
    	char payload[4096];
    };
    che so che potrà contenere fino ad un massimo di 4096 caratteri, ma anche meno! Posso usare cmq come contenitore un array di chars a lunghezza fissa, oppure è meglio usare vector, oppure:

    char payload = new char[n] ???

    grazie
    Alla batteria dai retta ballA

  9. #9
    Dipende da quello che ci devi fare, da quante ne devi allocare, dalla dimensione media del tuo payload, ... Comunque se intendi implementare una classe che gestisca della memoria allocata dinamicamente, ricordati di tutte le complicazioni varie del distruttore, del costruttore di copia e dell'operatore di assegnamento. Ho scritto una risposta qualche settimana fa su StackOverflow piuttosto completa sull'argomento.
    Amaro C++, il gusto pieno dell'undefined behavior.

  10. #10
    Ok, allora per chiudere il thread ti chiedo se secondo te il codice che segue può portare a delle memory leaks di qualche tipo:

    codice:
    #include <windows.h>
    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <boost/circular_buffer.hpp>
    using namespace std;
    using namespace boost;
    
    void getDateTime(char * szTime);
    const int numbuff = 3;
    const int buflen  = 30;
    
    struct buffer
    {
    	char data[1024];
    	int bytesRecorded;
    	buffer(const char * data_, const int bytesRecorded_) :
    		bytesRecorded(bytesRecorded_)
    		{
    			copy(data_, data_ + (bytesRecorded_ * sizeof(char)), data);
    		}
    };
    
    
    int main()
    {
    	circular_buffer<buffer> cb(numbuff);
    
    	// Insert elements
    	cout << "Push elements:" << endl;
    	for(int i = 0; i < 10; i++)
    	{
    		char szTime[30]; getDateTime(szTime);
    
    		cb.push_back( buffer(szTime, 30) );
    
    		cout << szTime << endl;
    
    		Sleep(1000);
    	}
    
    	// Show elements:
    	cout << "Show elements:" << endl;
    	for(int i = 0; i<(int)cb.size(); i++)
    	{
    		cout << &cb[i].data[0] << endl;
    	}
    
    	system("pause");
    	return EXIT_SUCCESS;
    }
    
    void getDateTime(char * szTime)
    {
    	time_t rawtime = time(NULL);
    	struct tm timeinfo;
    	gmtime_s(&timeinfo, &rawtime);
    	strftime(szTime, 30, "%a, %d %b %Y %X GMT", &timeinfo);
    }
    inoltre il codice mi sembra molto vicino al C++ anche se non usa string...(ma ti ho già spiegato che non posso!)

    grazie
    Alla batteria dai retta ballA

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.