manipulation de std::vector problème de mémoire
Dernière réponse : dans Programmation
Bonjour a tous!
Je suis confronte a de serieux problemes avec la manipulation des std::vector en c++ avec Visual .Net 2003. J' ai developpe un algorithme qui doit gerer des listes d objets assez complexes j utilise donc des vector pour les stocker.
Jusque la pas trop de probleme mais par la suite j ai tente d integrer mon algorithme a un autre projet que j ai adapte et les methodes communiquent par le biais de std::vector< std::vector<int> > de maniere iterative. Mais mon programme fini par s arreter pour cause de probleme de memoire de ce type:
Citation:
Microsoft C++ exception: std::bad_alloc @ 0x0012ecac.
Y a t-il un probleme connu avec le fait d envoyer d envoyer en parametres des pointeurs sur des std::vector et de retourner des objets de type std::vector par le biais de methodes d'objet ou de methode statique.
Voici un exemple de code contenue dans une methode appele de facon iterative:
Code :
std::vector<int> mvRef;
int num4x4Blocks = width/4*height/4;
blocks4x4.reserve(num4x4Blocks);
mvRef.reserve(2*num4x4Blocks);
//
//
// Insertion des valeurs dans mvRef a l'aide de differentes
// methodes
//
//
return mvRef; // Ceci cree une erreur de type memory a la 2 eme
// iteration
Notez qu'il suffit de modifier un bout de code pour que l erreur apparaissent dans une autre methode qui a le meme genre de procede
Toutes vos suggestions sont les bienvenues...
Je suis confronte a de serieux problemes avec la manipulation des std::vector en c++ avec Visual .Net 2003. J' ai developpe un algorithme qui doit gerer des listes d objets assez complexes j utilise donc des vector pour les stocker.
Jusque la pas trop de probleme mais par la suite j ai tente d integrer mon algorithme a un autre projet que j ai adapte et les methodes communiquent par le biais de std::vector< std::vector<int> > de maniere iterative. Mais mon programme fini par s arreter pour cause de probleme de memoire de ce type:
Citation:
Microsoft C++ exception: std::bad_alloc @ 0x0012ecac.
Y a t-il un probleme connu avec le fait d envoyer d envoyer en parametres des pointeurs sur des std::vector et de retourner des objets de type std::vector par le biais de methodes d'objet ou de methode statique.
Voici un exemple de code contenue dans une methode appele de facon iterative:
Code :
std::vector<int> mvRef;
int num4x4Blocks = width/4*height/4;
blocks4x4.reserve(num4x4Blocks);
mvRef.reserve(2*num4x4Blocks);
//
//
// Insertion des valeurs dans mvRef a l'aide de differentes
// methodes
//
//
return mvRef; // Ceci cree une erreur de type memory a la 2 eme
// iteration
Notez qu'il suffit de modifier un bout de code pour que l erreur apparaissent dans une autre methode qui a le meme genre de procede
Toutes vos suggestions sont les bienvenues...
Autres pages sur : manipulation std vector probleme memoire
Lassé par la pub ? Créez un compte
Ok si tu souhaites avoir un peu plus de details et bien en voici:
std::vector<int> Multigrid::methodeMultigrid16x16(unsigned char* I_Y, unsigned char* P_Y, unsigned char* prediction,
unsigned char* predictionBlocks, unsigned char* blocksMap, int step, int width,
int height, int precision, unsigned int* complexity, unsigned char* prediction4x4)
{
int num128x128Blocks = width/128*height/128;
int numLevels = log10(double(128/(precision)))/log10(2.0)+1;
int maxNumBlocks = num128x128Blocks;
int add = num128x128Blocks;
for (int i=0; i<numLevels-1; i++)
{
add = 4*add;
maxNumBlocks = maxNumBlocks + add;
}
int count=0;
std::vector<Block*> blocks;
blocks.reserve(maxNumBlocks);
for (int i=0; i<maxNumBlocks; i++)
{
Block* block = new Block();
blocks.push_back(block);
}
Block:
rocess(I_Y, P_Y, &count, step, width, height, &numLevels, complexity, blocks);
// Block vector for mapping
std::vector<Block*> blocks4x4;
std::vector<int> mvRef;
int num4x4Blocks = width/4*height/4;
blocks4x4.reserve(num4x4Blocks);
mvRef.reserve(2*num4x4Blocks);
for (int i=0; i<num4x4Blocks; i++)
{
Block* block = new Block();
blocks4x4.push_back(block);
}
//Mapping multigrid Blocks to 4x4 blocks
Block::mappingBlocks4x4(&count,blocks4x4, blocks);
Multigrid::constructMultigridPrediction(I_Y, prediction,count, predictionBlocks, blocksMap,blocks);
Multigrid::constructPrediction4x4(I_Y, prediction4x4, num4x4Blocks, blocks4x4);
blocks.clear();
//Inserting motion vectors in the motion Vector list
for (int i=0; i<num4x4Blocks; i++)
{
int v0 = blocks4x4->motionVector[0];
int v1 = blocks4x4->motionVector[1];
mvRef.push_back(v0);
mvRef.push_back(v1);
}
blocks4x4.clear();
return mvRef;
}
En general les valeurs de width et de height sont respectivement 512 et 384, mais le but final serait d utiliser des valeurs 1024 et 768
Et je pense certainement qu'une premiere chose a faire serait d'envoyer des pointeurs sur les objets de types vecteurs a la methode Block:
rocess plutot que les objets eux memes afin de ne pas surcharger le programme du point de vue allocation memoire de plus que cette methode ne fait que de modifier les differents attribus des objets de type Block contenus dans les vecteurs
std::vector<int> Multigrid::methodeMultigrid16x16(unsigned char* I_Y, unsigned char* P_Y, unsigned char* prediction,
unsigned char* predictionBlocks, unsigned char* blocksMap, int step, int width,
int height, int precision, unsigned int* complexity, unsigned char* prediction4x4)
{
int num128x128Blocks = width/128*height/128;
int numLevels = log10(double(128/(precision)))/log10(2.0)+1;
int maxNumBlocks = num128x128Blocks;
int add = num128x128Blocks;
for (int i=0; i<numLevels-1; i++)
{
add = 4*add;
maxNumBlocks = maxNumBlocks + add;
}
int count=0;
std::vector<Block*> blocks;
blocks.reserve(maxNumBlocks);
for (int i=0; i<maxNumBlocks; i++)
{
Block* block = new Block();
blocks.push_back(block);
}
Block:
rocess(I_Y, P_Y, &count, step, width, height, &numLevels, complexity, blocks);// Block vector for mapping
std::vector<Block*> blocks4x4;
std::vector<int> mvRef;
int num4x4Blocks = width/4*height/4;
blocks4x4.reserve(num4x4Blocks);
mvRef.reserve(2*num4x4Blocks);
for (int i=0; i<num4x4Blocks; i++)
{
Block* block = new Block();
blocks4x4.push_back(block);
}
//Mapping multigrid Blocks to 4x4 blocks
Block::mappingBlocks4x4(&count,blocks4x4, blocks);
Multigrid::constructMultigridPrediction(I_Y, prediction,count, predictionBlocks, blocksMap,blocks);
Multigrid::constructPrediction4x4(I_Y, prediction4x4, num4x4Blocks, blocks4x4);
blocks.clear();
//Inserting motion vectors in the motion Vector list
for (int i=0; i<num4x4Blocks; i++)
{
int v0 = blocks4x4->motionVector[0];
int v1 = blocks4x4->motionVector[1];
mvRef.push_back(v0);
mvRef.push_back(v1);
}
blocks4x4.clear();
return mvRef;
}
En general les valeurs de width et de height sont respectivement 512 et 384, mais le but final serait d utiliser des valeurs 1024 et 768
Et je pense certainement qu'une premiere chose a faire serait d'envoyer des pointeurs sur les objets de types vecteurs a la methode Block:
rocess plutot que les objets eux memes afin de ne pas surcharger le programme du point de vue allocation memoire de plus que cette methode ne fait que de modifier les differents attribus des objets de type Block contenus dans les vecteurs
desole
[code]
std::vector<int> Multigrid::methodeMultigrid16x16(unsigned char* I_Y, unsigned char* P_Y, unsigned char* prediction,
unsigned char* predictionBlocks, unsigned char* blocksMap, int step, int width,
int height, int precision, unsigned int* complexity, unsigned char* prediction4x4)
{
int num128x128Blocks = width/128*height/128;
int numLevels = log10(double(128/(precision)))/log10(2.0)+1;
int maxNumBlocks = num128x128Blocks;
int add = num128x128Blocks;
for (int i=0; i<numLevels-1; i++)
{
add = 4*add;
maxNumBlocks = maxNumBlocks + add;
}
int count=0;
std::vector<Block*> blocks;
blocks.reserve(maxNumBlocks);
for (int i=0; i<maxNumBlocks; i++)
{
Block* block = new Block();
blocks.push_back(block);
}
Block:
rocess(I_Y, P_Y, &count, step, width, height, &numLevels, complexity, blocks);
// Block vector for mapping
std::vector<Block*> blocks4x4;
std::vector<int> mvRef;
int num4x4Blocks = width/4*height/4;
blocks4x4.reserve(num4x4Blocks);
mvRef.reserve(2*num4x4Blocks);
for (int i=0; i<num4x4Blocks; i++)
{
Block* block = new Block();
blocks4x4.push_back(block);
}
//Mapping multigrid Blocks to 4x4 blocks
Block::mappingBlocks4x4(&count,blocks4x4, blocks);
Multigrid::constructMultigridPrediction(I_Y, prediction,count, predictionBlocks, blocksMap,blocks);
Multigrid::constructPrediction4x4(I_Y, prediction4x4, num4x4Blocks, blocks4x4);
blocks.clear();
//Inserting motion vectors in the motion Vector list
for (int i=0; i<num4x4Blocks; i++)
{
int v0 = blocks4x4->motionVector[0];
int v1 = blocks4x4->motionVector[1];
mvRef.push_back(v0);
mvRef.push_back(v1);
}
blocks4x4.clear();
return mvRef;
}
[code]
std::vector<int> Multigrid::methodeMultigrid16x16(unsigned char* I_Y, unsigned char* P_Y, unsigned char* prediction,
unsigned char* predictionBlocks, unsigned char* blocksMap, int step, int width,
int height, int precision, unsigned int* complexity, unsigned char* prediction4x4)
{
int num128x128Blocks = width/128*height/128;
int numLevels = log10(double(128/(precision)))/log10(2.0)+1;
int maxNumBlocks = num128x128Blocks;
int add = num128x128Blocks;
for (int i=0; i<numLevels-1; i++)
{
add = 4*add;
maxNumBlocks = maxNumBlocks + add;
}
int count=0;
std::vector<Block*> blocks;
blocks.reserve(maxNumBlocks);
for (int i=0; i<maxNumBlocks; i++)
{
Block* block = new Block();
blocks.push_back(block);
}
Block:
rocess(I_Y, P_Y, &count, step, width, height, &numLevels, complexity, blocks);// Block vector for mapping
std::vector<Block*> blocks4x4;
std::vector<int> mvRef;
int num4x4Blocks = width/4*height/4;
blocks4x4.reserve(num4x4Blocks);
mvRef.reserve(2*num4x4Blocks);
for (int i=0; i<num4x4Blocks; i++)
{
Block* block = new Block();
blocks4x4.push_back(block);
}
//Mapping multigrid Blocks to 4x4 blocks
Block::mappingBlocks4x4(&count,blocks4x4, blocks);
Multigrid::constructMultigridPrediction(I_Y, prediction,count, predictionBlocks, blocksMap,blocks);
Multigrid::constructPrediction4x4(I_Y, prediction4x4, num4x4Blocks, blocks4x4);
blocks.clear();
//Inserting motion vectors in the motion Vector list
for (int i=0; i<num4x4Blocks; i++)
{
int v0 = blocks4x4->motionVector[0];
int v1 = blocks4x4->motionVector[1];
mvRef.push_back(v0);
mvRef.push_back(v1);
}
blocks4x4.clear();
return mvRef;
}
non pardon:
std::vector<int> Multigrid::methodeMultigrid16x16(unsigned char* I_Y, unsigned char* P_Y, unsigned char* prediction, unsigned char* predictionBlocks, unsigned char* blocksMap, int step, int width, int height, int precision, unsigned int* complexity, unsigned char* prediction4x4) { int num128x128Blocks = width/128*height/128; int numLevels = log10(double(128/(precision)))/log10(2.0)+1; int maxNumBlocks = num128x128Blocks; int add = num128x128Blocks; for (int i=0; i<numLevels-1; i++) { add = 4*add; maxNumBlocks = maxNumBlocks + add; } int count=0; std::vector<Block*> blocks; blocks.reserve(maxNumBlocks); for (int i=0; i<maxNumBlocks; i++) { Block* block = new Block(); blocks.push_back(block); } Block::process(I_Y, P_Y, &count, step, width, height, &numLevels, complexity, blocks); // Block vector for mapping std::vector<Block*> blocks4x4; std::vector<int> mvRef; int num4x4Blocks = width/4*height/4; blocks4x4.reserve(num4x4Blocks); mvRef.reserve(2*num4x4Blocks); for (int i=0; i<num4x4Blocks; i++) { Block* block = new Block(); blocks4x4.push_back(block); } //Mapping multigrid Blocks to 4x4 blocks Block::mappingBlocks4x4(&count,blocks4x4, blocks); Multigrid::constructMultigridPrediction(I_Y, prediction,count, predictionBlocks, blocksMap,blocks); Multigrid::constructPrediction4x4(I_Y, prediction4x4, num4x4Blocks, blocks4x4); blocks.clear(); //Inserting motion vectors in the motion Vector list for (int i=0; i<num4x4Blocks; i++) { int v0 = blocks4x4[i]->motionVector[0]; int v1 = blocks4x4[i]->motionVector[1]; mvRef.push_back(v0); mvRef.push_back(v1); } blocks4x4.clear(); return mvRef; }
Voici les instances de Block:
Ok donc lorsque les vecteus contiennent des valeurs pointees et qu on fait un appel a clear(), ces derniers ne sont pas supprimes?
Donc je dois effectue une boucle du genre:
?
int position[2]; int width; int height; int level; bool isSplitted; bool isCreated; bool mustSplit; int motionVector[2]; int parentNeighbour1Vector[2]; int parentNeighbour2Vector[2]; int parentNeighbour3Vector[2];
Ok donc lorsque les vecteus contiennent des valeurs pointees et qu on fait un appel a clear(), ces derniers ne sont pas supprimes?
Donc je dois effectue une boucle du genre:
for (int i=0; i<num4x4Blocks; i++) { delete blocks4x4[i]; }
?
Citation :
Voici les instances de Block:
int position[2]; int width; int height; int level; bool isSplitted; bool isCreated; bool mustSplit; int motionVector[2]; int parentNeighbour1Vector[2]; int parentNeighbour2Vector[2]; int parentNeighbour3Vector[2];
Citation :
Ok donc lorsque les vecteus contiennent des valeurs pointees et qu on fait un appel a clear(), ces derniers ne sont pas supprimes?
Citation :
Donc je dois effectue une boucle du genre:
for (int i=0; i<num4x4Blocks; i++) { delete blocks4x4[i]; }
?
non, autant etre propre et utiliser les itérateurs qui sont la pour ca
for ( std::vector<Block*>::iterator it = blocks.begin() ; it != blocks.end(); ++it) { delete *it; } bocks.clear();
et tu fais pareil pour blocks4x4
je te conseil aussi de faire des typedef pour tes vecteurs que tu utilises souvent, cela rendra ton code beaucoup plus lisible
J'ai modifier le code comme tu me l'as conseille mais maintenant le probleme apparait a un endroit plus avance de la meme iteration:
Voici les messages du debug:
Et l endroit precis du crash:
std::vector<int> Multigrid::methodeMultigrid16x16(unsigned char* I_Y, unsigned char* P_Y, unsigned char* prediction, unsigned char* predictionBlocks, unsigned char* blocksMap, int step, int width, int height, int precision, unsigned int* complexity, unsigned char* prediction4x4) { int num128x128Blocks = width/128*height/128; int numLevels = log10(double(128/(precision)))/log10(2.0)+1; int maxNumBlocks = num128x128Blocks; int add = num128x128Blocks; for (int i=0; i<numLevels-1; i++) { add = 4*add; maxNumBlocks = maxNumBlocks + add; } int count=0; std::vector<Block*> blocks; blocks.reserve(maxNumBlocks); for (int i=0; i<maxNumBlocks; i++) { Block* block = new Block(); //--------> APPARITION DU MEME PROBLEME DE MEMOIRE!!!!!!!! blocks.push_back(block); } Block::process(I_Y, P_Y, &count, step, width, height, &numLevels, complexity, blocks); // Block vector for mapping std::vector<Block*> blocks4x4; std::vector<int> mvRef; int num4x4Blocks = width/4*height/4; blocks4x4.reserve(num4x4Blocks); mvRef.reserve(2*num4x4Blocks); for (int i=0; i<num4x4Blocks; i++) { Block* block = new Block(); blocks4x4.push_back(block); } //Mapping multigrid Blocks to 4x4 blocks Block::mappingBlocks4x4(&count,blocks4x4, blocks); Multigrid::constructMultigridPrediction(I_Y, prediction,count, predictionBlocks, blocksMap,blocks); Multigrid::constructPrediction4x4(I_Y, prediction4x4, num4x4Blocks, blocks4x4); for ( std::vector<Block*>::iterator it = blocks.begin() ; it != blocks.end(); ++it) { delete *it; } blocks.clear(); //Inserting motion vectors in the motion Vector list for (int i=0; i<num4x4Blocks; i++) { int v0 = blocks4x4[i]->motionVector[0]; int v1 = blocks4x4[i]->motionVector[1]; mvRef.push_back(v0); mvRef.push_back(v1); } for ( std::vector<Block*>::iterator it = blocks4x4.begin() ; it != blocks4x4.end(); ++it) { delete *it; } blocks4x4.clear(); return mvRef; }
Voici les messages du debug:
kernel32.dll!7c81eb33() kernel32.dll!7c81eb33() msvcr71d.dll!_nh_malloc_dbg(unsigned int nSize=1, int nhFlag=3, int nBlockUse=1240264, const char * szFileName=0x0012ee50, int nLine=1240724) Line 267 + 0x7 C msvcr71d.dll!_CxxThrowException(void * pExceptionObject=0x0012ece4, const _s__ThrowInfo * pThrowInfo=0x104f6150) + 0x39 C++ msvcp71d.dll!std::_Nomemory() Line 10 C++ > H264AVCEncoderLibTestStaticd.exe!operator new(unsigned int size=60) Line 15 C++ H264AVCEncoderLibTestStaticd.exe!Multigrid::methodeMultigrid16x16(unsigned char * I_Y=0x06e89ff8, unsigned char * P_Y=0x04d7e028, unsigned char * prediction=0x06eba038, unsigned char * predictionBlocks=0x06eea078, unsigned char * blocksMap=0x06f1a0b8, int step=16, int width=512, int height=384, int precision=4, unsigned int * complexity=0x0012eee4, unsigned char * prediction4x4=0x06f4a0f8) Line 84 + 0x7 C++
Et l endroit precis du crash:
void *__cdecl operator new(size_t size) _THROW1(_STD bad_alloc) { // try to allocate size bytes void *p; while ((p = malloc(size)) == 0) if (_callnewh(size) == 0) _STD _Nomemory(); return (p); //------------>ENDROIT DU CRASH!!!!!!!!!!!!!!!!!! }
maxNumBlocks est d un ordre de grandeur allant de 17'000 environ. En ce qui concerne add je l utilise simplement de blocks (= de carres, si tu veux) maximum que j obtient lorsque je cadrille un carre d une taille width*height en commencant par des blocks 128*128 ensuite 64*64 et ainsi de suite et ce jusqu'a precision*precision. Dans le cas precis precision vaut 4
Effectivement je n utilise pas tout mais ce nombre correspond a la borne maximale. Effectivement peut etre que je devrais tenter de reduire ce nombre a une valeur plus plausible mais quoiqu il en soit je dois absolument utiliser les 12'288 objets de blocks4x4, pas de reduction possible a ce niveau la. D autant plus que l ideal serait que j en utilise 4x plus a la longue mais bon....c est encore une autre histoire
Finalement je me suis resigne a utilier un tableau de pointeurs a la place des vecteurs car meme n utilisant que du referencement ( c est a dire en ne transmettant jamais une copie d un objet envoye en parametre a une methode mais plutot la reference de ce dernier) et ca plante moins facilement. Mais comme mon programme est engage dans un boucle qui devrais selon les cas atteindre jusqu a un maximum de 1000 iterations environ, Je fini tout de meme par avoir un runtime error et mon programme se voit forcer d etre interrompu par le system. Pourtant ma contribution n est qu un plug in a un soft qui tourne deja sans aucun probleme meme avec plus de 1000 iteration. Je sais que la coquille vient de mon bout de code mais ou exactement? aucune idee. Je crois avoir tout essaye. Cependant j ai remarque un phenomene bizarre: lorsque la reference a **blocks est envoye en paremetre (&blocks) a une methode qui ne fait que de lire les valeurs pointee sans en modifier aucune elles sont alteree des la fin de l execution de la methode. D ou peut venir ce genre de phenomenes en general?
Lassé par la pub ? Créez un compte
- Contenus similaires :
- ForumResoudre probleme de memoire packard bell
- ForumProblème aprés un changement de barrettes mémoire
- ForumProbleme mémoire DDR3 Linpack
- ForumProbleme de memoire sur pc packardbell
- ForumPas de boot, probleme memoire?
- ForumProblème de mémoire avec ma ps2
- ForumProbleme installation barrette memoire
- ForumProbleme avec un baladeur LISTO 'plus rien en memoire'
- ForumProblème de démarrage/mémoire
- Voir plus
)
![[:pingouino] [:pingouino]](http://m.bestofmedia.com/sfp/design/usr/fr/smilies/9e/8c/pingouino.gif)