Tout d'abord, tout ce que G_LOCK_DEFINE
fait est de créer une variable GMutex
, dont le nom code le nom de la variable qu'il protège, par ex. G_LOCK_DEFINE(mSomeCounter)
devient GMutex g__mSomeCounter_lock;
. Ainsi, nous pouvons étendre votre code à quelque chose comme:
class CSomeClass {
private:
gulong mSomeCounter;
GMutex g__mSomeCounter_lock;
public:
CSomeClass();
};
CSomeClass::CSomeClass()
{
g_mutex_lock(&g__mSomeCounter_lock);
mSomeCounter = 0;
g_mutex_unlock(&g__mSomeCounter_lock);
}
Le problème fondamental est que vous n'êtes pas une initialisation des membres de la classe CSomeClass
. Vous attribuez des valeurs à et d'entre eux dans le constructeur, mais vous ne les initialisez définitivement pas. Il y a une différence entre l'affectation entre accolades, et en utilisant un initialiseur, tels que:
CSomeClass::CSomeClass() : mSomeCounter(0)
En conséquence, le mutex qui est créé, nommé contre la variable peut contenir des déchets. Il n'y a probablement rien dans le code glib qui aurait changé pour que cela se produise, il est plus probable que les changements apportés aux autres bibliothèques aient changé la disposition de la mémoire de votre application, découvrant le bogue.
Les glib documentation conseils que vous devez g_mutex_init
mutex:
qui a été alloué sur la pile, ou dans le cadre d'une structure plus grande
Vous n'avez pas besoin de g_mutex_init
mutex que :
Il n'est pas nécessaire d'initialiser un mutex qui a été alloué statiquement
Les instances de classe sont presque toujours et non allouées de manière statique.
Vous devez corriger votre constructeur pour vous assurer qu'il initialise correctement le mutex, par ex.:
CSomeClass::CSomeClass()
{
g_mutex_init(&G_LOCK_NAME(mSomeCounter));
G_LOCK(mSomeCounter);
mSomeCounter = 0;
G_UNLOCK(mSomeCounter);
}
TBH, je mettrais le mutex dans un support de classe, et l'initialiser dans le cadre de cela, plutôt que la façon dont vous le faites, pour qu'il s'initialisé, verrouillé et déverrouillé partie de la sémantique standard C++ RAII.
Si vous utilisez un petit talon principal, quelque chose comme:
main() {
{ CSomeClass class1; }
{ CSomeClass class2; }
{ CSomeClass class3; }
}
et votre code, il y a une bonne chance, il se bloque de toute façon. (Mon mac est écrasé l'exemple avec:. GLib (gthread-posix.c): Unexpected error from C library during 'pthread_mutex_lock': Invalid argument. Aborting.
quelques simples, par exemple, non production emballages pour aider à RAII:
class CGMutex {
GMutex mutex;
public:
CGMutex() {
g_mutex_init(&mutex);
}
~CGMutex() {
g_mutex_clear(&mutex);
}
GMutex *operator&() {
return &mutex;
}
};
class CGMutexLocker {
CGMutex &mRef;
public:
CGMutexLocker(CGMutex &mutex) : mRef(mutex) {
g_mutex_lock(&mRef);
}
~CGMutexLocker() {
g_mutex_unlock(&mRef);
}
};
class CSomeClass {
private:
gulong mSomeCounter;
CGMutex mSomeCounterLock;
public:
CSomeClass();
};
CSomeClass::CSomeClass()
{
CGMutexLocker locker(mSomeCounterLock); // lock the mutex using the locker
mSomeCounter = 0;
}
L'initialisation mSomeCounter assure que le compteur s'initialisé, sinon il aura poubelle