OVH Cloud OVH Cloud

Création de macro

27 réponses
Avatar
Michaël Delva
Bonjour à tous,

j'utilise DirectShow, et je me retrouve très souvent à employer ce genre de
syntaxe pour vérifier le bon déroulement du code:

hr = this->ConnectFilters(pGraph,pInfTee,pMux);
if (FAILED(hr))
{
ShowMessage("Impossible de connecter pInfTee à pMux");
return false;
}

FAILED étant une macro de DIrectShow permettant de vérifier que hr est
différent de S_OK, la valeur de retour indiquant que tout s'est bien passé.

Je voudrais créer une macro me permettant de réduire le code, quelque chose
du style:

TEST_FAILED(this->ConnectFilters(pGraph,pInfTee,pMux),"Impossible de
connecter pInfTee à pMux");

et qui ait le même comportement que le code ci-dessus...

Seulement je sais absolument pas utiliser les macros...

Une âme charitable pourrait-elle m'aider?

Merci d'avance!

7 réponses

1 2 3
Avatar
Michaël Delva
Ok, merci de tes solutions, elles correspondent parfaitement...

Mais là je suis face à un autre problème:

Soient les classes suivantes:

class A
{
public:
A() {};
};


class B
{
private:
boost::scoped_ptr<A> a1;
boost::scoped_ptr<A> a2;

foo();
public:
B();
};

Le constructeur de B

B::B()
{
foo();
}

B::foo()
{
try
{
a1.reset(new A);
a2.reset(new A);
}
catch (const MyException & e)
{
throw;
}
}

Mon problème est que si A lance une exception MyException pendant la
construction de a1, effectivement a2 n'est pas construit, l'exception
passe dans le catch, mais CodeGuard me signale une fuite de mémoire
m'indiquant que a1 est quand même construit, et n'a pas été correctement
détruit, alors que si je ne me trompe pas il ne devrait pas l'être
puisque l'exception se déclenche dans le constructeur!

J'ai essayé de mettre des try catch dans le constructeur de A, dans celui
de B (en plus de ceux dans foo) mais évidemment ça ne sert à rien...

J'ai bien vérifié toutes les étapes de construction de A, et tous les
pointeurs sont enchassés dans des pointeurs intelligents... Donc là je
nage complétement...

Auriez-vous une réponse à ce problème?

Merci d'avance
Avatar
Fabien LE LEZ
On 08 Sep 2004 23:15:06 GMT, "Michaël Delva"
:

B::foo()
{
try
{
a1.reset(new A);
a2.reset(new A);
}
catch (const MyException & e)
{
throw;
}
}


Plus simple et ayant exactement le même fonctionnement :

B::foo()
{
a1.reset(new A);
a2.reset(new A);
}

mais CodeGuard me signale une fuite de mémoire
m'indiquant que a1 est quand même construit, et n'a pas été correctement
détruit


Qu'est-ce que ça donne si tu utilises std::auto_ptr<> à la place de
boost::scoped_ptr<> ?


--
;-)

Avatar
Michaël Delva
Ce cas ne se produit que lorsque les scoped_ptr (j'ai essayé avec des
shared_ptr, c'est le même problème) sont dans la déclaration de la classe.

SI j'ai:

class A
{
public:
A() {};
};


class B
{
private:
foo();
public:
B();
};

Le constructeur de B

B::B()
{
foo();
}

B::foo()
{
try
{
boost::scoped_ptr<A> a1(new A);
boost::scoped_ptr<A> a2(new A);
}
catch (const MyException & e)
{
throw;
}
}

Ben là ça marche nickel...
Avatar
Michaël Delva
Qu'est-ce que ça donne si tu utilises std::auto_ptr<> à la place de
boost::scoped_ptr<> ?



Même chose...

par contre en ne créant pas a1 et a2 avec new, comme suit:

class B
{
private:
foo();

A a1;
A a2;
public:
B();
};

B::B()
{
foo();
}

B::foo()
{
a1 = A;
a2 = A;
}

tout marche impecc'

Le problème viendrait de mes constructeurs?

Avatar
Fabien LE LEZ
On 08 Sep 2004 23:15:06 GMT, "Michaël Delva"
:

CodeGuard me signale une fuite de mémoire
m'indiquant que a1 est quand même construit, et n'a pas été correctement
détruit, alors que si je ne me trompe pas il ne devrait pas l'être
puisque l'exception se déclenche dans le constructeur!


Attention : a1, objet de type boost::scoped_ptr<A>, est bien
construit, car membre de B. C'est l'objet sur lequel a1 garde un
pointeur, qui n'a pas été construit.

De toutes façons, d'après le message, le problème me semble venir de
plus haut (i.e. de la fonction qui crée l'objet de classe B).

Essaie le programme suivant et regarde ce que Codeguard en pense :



class Exception {};

class A
{
public:
A (bool lance_exception) { if (lance_exception) throw Exception();
}
};

class B
{
public:
B();

int f() const { return 4; }

private:
std::auto_ptr<A> a1;
std::auto_ptr<A> a2;
};

B::B()
{
a1.reset (new A (false));
a2.reset (new A (true));
}

int main()
{
try
{
B b;
cerr << "B::f() : " << b.f() << endl;
}
catch (Exception const&)
{
cerr << "Une exception a été lancée" << endl;
}
}





--
;-)

Avatar
Michaël Delva
Essaie le programme suivant et regarde ce que Codeguard en pense :


Pas de fuite mémoire...

Avatar
Michaël Delva
Je ne vois pas d'où pourrait venir le problème...

As-tu une idée?

Pour info, voici le constructeur qui pose problème:

//----------------------------------------------------------------------
__fastcall DS_Affich_Video::DS_Affich_Video(HWND handle_fenetre, const
WideString & path_video)
: path_video(path_video), handle_fenetre(handle_fenetre)
{
Lang = Language::getInstance();

DS_Failed(CoInitialize(NULL),Lang->Get_Sequence(4));

VerifyVMR9();

DS_Failed(pGraph.CoCreateInstance(CLSID_FilterGraph),Lang->Get_Sequence
(9) + " IGraphBuilder");

DS_Failed(InitializeWindowlessVMR(&pVmr),Lang->Get_Sequence(5));

DS_Failed(RenderFileToVMR9(pGraph, path_video, pVmr, true),Lang->
Get_Sequence(6));

Add_All_Interfaces();

CheckVisibility();

SetNotifyWindow();
}

Chacune des fonctions permet d'initialiser le rendu vidéo...

Quand je veux tester avec une exception, je donne un faux path de
fichier, et l'exception se lance dans la fonction RenderFileToVMR9, que
voici (exception lancée dans l'appel à AddSourceFilter)

//----------------------------------------------------------------------
HRESULT __fastcall DS_Affich_Video::RenderFileToVMR9(IGraphBuilder * pGB,
WideString path_video, IBaseFilter * pRenderer, bool bRenderAudio = true)
{
CComPtr<IPin> pOutputPin;
CComPtr<IBaseFilter> pAudioRenderer;

if (bRenderAudio)
{
DS_Failed(pAudioRenderer.CoCreateInstance(CLSID_DSoundRender),Lang->
Get_Sequence(9) + " CLSID_DSoundRender");
DS_Failed(pGB->AddFilter(pAudioRenderer, L"Audio Renderer"),Lang->
Get_Sequence(25) + " pAudioRenderer");
}

CComPtr<IBaseFilter> pSource;

if (!IsWindowsMediaFile(path_video))
{
DS_Failed(pGB->AddSourceFilter(path_video, L"SOURCE",
&pSource),Lang->Get_Sequence(25) + " pSource");
DS_Failed(GetUnconnectedPin(pSource, PINDIR_OUTPUT,
&pOutputPin),Lang->Get_Sequence(28));
}
else
{
ShowMessage(Lang->Get_Sequence(29));
return E_FAIL;
}

CComQIPtr<IFilterGraph2> pFG(pGB);
if (!pFG)
ShowMessage(Lang->Get_Sequence(9) + " IFilterGraph2");

DS_Failed(pFG->RenderEx(pOutputPin,
AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL),Lang->Get_Sequence(30));

if (pAudioRenderer != NULL)
{
CComPtr<IPin> pUnconnectedPin;

HRESULT hrPin = GetUnconnectedPin(pAudioRenderer, PINDIR_INPUT,
&pUnconnectedPin);

if (SUCCEEDED(hrPin) && (pUnconnectedPin != NULL))
{
pUnconnectedPin.Release();
DS_Failed(pGB->RemoveFilter(pAudioRenderer),Lang->Get_Sequence
(31) + " pAudioRenderer");
}
}

DS_Failed(pVMRWC->GetNativeVideoSize(&width,&height,NULL,NULL),Lang->
Get_Sequence(32));

return S_OK;
}

Après avoir lancé l'exception, le programme quitte le contructeur de
DS_Affich_Video, mais j'ai quand même cette erreur de fuite mémoire...
1 2 3