Ürünlerimizden biriyle kullandığımız dahili bir bellek yöneticimiz var. Bellek yöneticisi new
ve delete
operatörlerini geçersiz kılar ve tek iş parçacıklı uygulamalarda düzgün çalışır. Ancak, şimdi de çok iş parçacıklı uygulamalarla çalışmak için görevlendirildim. Anladığım kadarıyla aşağıdaki sözde kod çalışmalı, ancak try_lock()
ile bile bir sıkışmada kalıyor. Herhangi bir fikir?std :: mutex kilidi, yeni operatörün üstünü açarken kilitleniyor
Güncelleme 1.
Nedenleri "Erişim ihlali":
#include <mutex>
std::mutex g_mutex;
bool g_systemInitiated = false;
/*!
\brief Overrides the Standard C++ new operator
\param size [in] Number of bytes to allocate
*/
void *operator new(size_t size)
{
if (g_systemInitiated == false) return malloc(size);
g_mutex.lock(); // Thread hangs forever here. g_mutex.try_lock() also hangs
...
}
int main(int argc, const char* argv[])
{
// Tell the new() operator that the system has initiated
g_systemInitiated = true;
...
}
Güncelleme 2.
: saymazsınız sonsuza asmak için#include <mutex>
std::mutex g_mutex;
/*!
\brief Overrides the Standard C++ new operator
\param size [in] Number of bytes to allocate
*/
void *operator new(size_t size)
{
g_mutex.lock(); // Access violation exception
...
}
nedenleri iplik
A özyinelemeli muteks da saymazsınız sonsuza asmak için iş parçacığı neden olur:
#include <mutex>
std::recursive_mutex g_mutex;
bool g_systemInitiated = false;
/*!
\brief Overrides the Standard C++ new operator
\param size [in] Number of bytes to allocate
*/
void *operator new(size_t size)
{
if (g_systemInitiated == false) return malloc(size);
g_mutex.lock(); // Thread hangs forever here. g_mutex.try_lock() also hangs
...
}
int main(int argc, const char* argv[])
{
// Tell the new() operator that the system has initiated
g_systemInitiated = true;
...
}
Güncelleme 3. Jonathan Wakely ben unique_lock
ve/veya lock_guard
, denemelisiniz ama kilit hala asılı önerdi
çevirmek.
unique_lock
testi:
#include <mutex>
std::mutex g_mutex;
std::unique_lock<std::mutex> g_lock1(g_mutex, std::defer_lock);
bool g_systemInitiated = false;
/*!
\brief Overrides the Standard C++ new operator
\param size [in] Number of bytes to allocate
*/
void *operator new(size_t size)
{
if (g_systemInitiated == false) return malloc(size);
g_lock1.lock(); // Thread hangs forever here the first time it is called
...
}
int main(int argc, const char* argv[])
{
// Tell the new() operator that the system has initiated
g_systemInitiated = true;
...
}
lock_guard
testi:
#include <mutex>
std::recursive_mutex g_mutex;
bool g_systemInitiated = false;
/*!
\brief Overrides the Standard C++ new operator
\param size [in] Number of bytes to allocate
*/
void *operator new(size_t size)
{
if (g_systemInitiated == false) return malloc(size);
std::lock_guard<std::mutex> g_lock_guard1(g_mutex); // Thread hangs forever here the first time it is called
...
}
int main(int argc, const char* argv[])
{
// Tell the new() operator that the system has initiated
g_systemInitiated = true;
...
}
benim sorun kilitlenmesi sırasında delete
C++ 11 muteks kütüphaneye tarafından çağrılan olduğunu düşünüyorum. delete
da şöyle geçersiz kılınır:
/*!
\brief Overrides the Standard C++ new operator
\param p [in] The pointer to memory to free
*/
void operator delete(void *p)
{
if (g_systemInitiated == false)
{
free(p);
}
else
{
std::lock_guard<std::mutex> g_lock_guard1(g_mutex);
...
}
}
Bu kilitleme veya açma sırasında new
veya delete
herhangi bir çağrı yumurtlamaya vermez kendi kilitleme yapmak için hariç için Her iyi çözüm göremiyorum durum kilitleyebilmenize neden olur.
Güncelleme 4. Ben new
veya delete
hiçbir aramaları var kendi özel özyinelemeli Muteksleri uyguladık
, ayrıca, aynı iş parçacığı kilitli blok girmek için izin verir.
#include <thread>
std::thread::id g_lockedByThread;
bool g_isLocked = false;
bool g_systemInitiated = false;
/*!
\brief Overrides the Standard C++ new operator
\param size [in] Number of bytes to allocate
*/
void *operator new(size_t size)
{
if (g_systemInitiated == false) return malloc(size);
while (g_isLocked && g_lockedByThread != std::this_thread::get_id());
g_isLocked = true; // Atomic operation
g_lockedByThread = std::this_thread::get_id();
...
g_isLocked = false;
}
/*!
\brief Overrides the Standard C++ new operator
\param p [in] The pointer to memory to free
*/
void operator delete(void *p)
{
if (g_systemInitiated == false)
{
free(p);
}
else
{
while (g_isLocked && g_lockedByThread != std::this_thread::get_id());
g_isLocked = true; // Atomic operation
g_lockedByThread = std::this_thread::get_id();
...
g_isLocked = false;
}
}
int main(int argc, const char* argv[])
{
// Tell the new() operator that the system has initiated
g_systemInitiated = true;
...
}
Güncelleme 5.
çalıştı Jonathan Wakely öneri ve kesinlikle C++ 11 muteksleri Microsoft'un uygulama ile ilgili bir sorun olduğu görülmektedir bulundu ; onun örneği, /MTd
(Çok iş parçacıklı Debug) derleyici bayrağıyla derlenmişse askıda kalıyor, ancak /MDd
(Çok iş parçacıklı Debug DLL) derleyici bayrağıyla derlenmişse iyi çalışıyor. Jonathan'ın doğru bir şekilde işaret ettiği gibi std::mutex
uygulamalarının constexpr
olması gerekiyor.
#include "stdafx.h"
#include <mutex>
#include <iostream>
bool g_systemInitiated = false;
std::mutex g_mutex;
void *operator new(size_t size)
{
if (g_systemInitiated == false) return malloc(size);
std::lock_guard<std::mutex> lock(g_mutex);
std::cout << "Inside new() critical section" << std::endl;
// <-- Memory manager would be called here, dummy call to malloc() in stead
return malloc(size);
}
void operator delete(void *p)
{
if (g_systemInitiated == false) free(p);
else
{
std::lock_guard<std::mutex> lock(g_mutex);
std::cout << "Inside delete() critical section" << std::endl;
// <-- Memory manager would be called here, dummy call to free() in stead
free(p);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
g_systemInitiated = true;
char *test = new char[100];
std::cout << "Allocated" << std::endl;
delete test;
std::cout << "Deleted" << std::endl;
return 0;
}
Güncelleme # Microsoft'a bir hata raporu Ekleyen 6
: Burada uygulama sorunu sınamak için kullanılan VS 2012 C++ kodu https://connect.microsoft.com/VisualStudio/feedback/details/776596/std-mutex-not-a-constexpr-with-mtd-compiler-flag#details
bunu bağlayabilirsiniz nasıl görmüyorum, nereye senin g_mutex tanımlıyorsunuz? iki deklarasyon var, bunlardan birinin ön tarafına sahip olmalısınız. –
Yeni ve silme işleçleriniz gerçekten ne yapıyorsunuz (bellek ayırma/boşaltma dışında)? –
@claptrap Bu sahte koddur. –