Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何调试或修复涉及boost::进程间托管共享内存的无休止循环和堆损坏问题?_C++_Boost_Visual C++ 2008_Boost Interprocess - Fatal编程技术网

C++ 如何调试或修复涉及boost::进程间托管共享内存的无休止循环和堆损坏问题?

C++ 如何调试或修复涉及boost::进程间托管共享内存的无休止循环和堆损坏问题?,c++,boost,visual-c++-2008,boost-interprocess,C++,Boost,Visual C++ 2008,Boost Interprocess,我有下面的“第一次机会异常”消息,它来自我编写的DLL,该DLL在我没有编写的可执行文件中运行。也就是说,DLL是一个插件。首次触发此异常时,打开共享内存映射文件的尝试失败。如果我忽略第一次出现的异常而只是运行,应用程序最终会冻结或崩溃 First-chance exception at 0x76a7c41f in notmyexe.exe: Microsoft C++ exception: boost::interprocess::interprocess_exception at memor

我有下面的“第一次机会异常”消息,它来自我编写的DLL,该DLL在我没有编写的可执行文件中运行。也就是说,DLL是一个插件。首次触发此异常时,打开共享内存映射文件的尝试失败。如果我忽略第一次出现的异常而只是运行,应用程序最终会冻结或崩溃

First-chance exception at 0x76a7c41f in notmyexe.exe: Microsoft C++ exception: boost::interprocess::interprocess_exception at memory location 0x002bc644..
几个小时后,它似乎是由一个代码块引起的,该代码块不断循环,直到预期的异常条件清除为止。事实证明,如果它从未清除,那么最终,这个异常会变成另一个低级异常情况和/或变成堆损坏。所有这些都只是为了使用Boost::interprocess打开共享内存区域

<> P>第一个复杂的事情是,在Visual C++ 2008项目中,第一个<代码> Boo::ItPoalExtExabutyExabue/Cuth>第一个机会异常不会被抛出,并被识别为它来自的位置,因为VisualC++ 2008编译器无法找到复杂的Boost味道模板代码。然而,通过单步遍历汇编语言视图,我发现了代码

我自己的代码中最顶层的一行开始出现问题:

  segment = new managed_shared_memory(   open_or_create
                                      ,  MEMORY_AREA_NAME
                                      , SHARED_AREA_SIZE );          
上述
managed_shared_memory
类来自interprocess_fwd.hpp,是boost共享内存API/头的标准部分。因为它是基于模板的,所以扩展到了2KCHARS长C++的Boost模板表达式,它由链接器和调试器截断在不同长度。Visual C++ 2008没有更多的源代码调试能力,似乎在这些限制发挥作用时。

例如,当它爆炸时,我得到以下调用堆栈:

    KernelBase.dll!76a7c41f()   
    [Frames below may be incorrect and/or missing, no symbols loaded for KernelBase.dll]    
    KernelBase.dll!76a7c41f()   
>   msvcr90d.dll!_malloc_dbg(unsigned int nSize=2290875461, int nBlockUse=264, const char * szFileName=0x01fcb983, int nLine=1962999808)  Line 160 + 0x1b bytes C++
    8bfc4d89()  
上面的堆栈转储中没有实际的最终用户编写的源函数

我应该如何调试它?第二,在Visual C++ 2008中有一些已知的Boost进程间的问题吗?第三,下面的boost代码在做什么?为什么它必须无休止地循环

boost::interprocess::basic_managed_shared_memory<char,
   boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,
        boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,
        boost::interprocess::iset_index>::basic_managed_shared_memory<char,boo...
无论如何,孩子们,不要试图在家里调试这个,下面是发生的情况:

<>最后,用我忍者般的能力单步通过几百万条汇编语言,我打败了Visual C++ 2008的调试程序,并找到了代码。p> 事实上,这就是爆炸的原因:
创建设备(dev.

这里有一些背景: 托管\u打开\u或\u创建\u impl.h行351

else if(type == DoOpenOrCreate){
         //This loop is very ugly, but brute force is sometimes better
         //than diplomacy. If someone knows how to open or create a
         //file and know if we have really created it or just open it
         //drop me a e-mail!
         bool completed = false;
         while(!completed){
            try{
               create_device<FileBased>(dev, id, size, perm, file_like_t()); // <-- KABOOM!
               created     = true;
               completed   = true;
            }
            catch(interprocess_exception &ex){
               if(ex.get_error_code() != already_exists_error){
                  throw;
               }
               else{
                  try{
                     DeviceAbstraction tmp(open_only, id, read_write);
                     dev.swap(tmp);
                     created     = false;
                     completed   = true;
                  }
                  catch(interprocess_exception &e){
                     if(e.get_error_code() != not_found_error){
                        throw;
                     }
                  }
                  catch(...){
                     throw;
                  }
               }
            }
            catch(...){
               throw;
            }
            thread_yield();
         }
      }
else if(type==DoOpenOrCreate){
//这个循环非常丑陋,但暴力有时更好
//而不是外交。如果有人知道如何打开或创建
//文件,并知道我们是否真的创建了它或只是打开它
//给我发封电子邮件!
bool completed=false;
而(!已完成){
试一试{

创建设备(dev、id、size、perm、file_like_t());//Boost充满了令人惊异和可怕的东西

在Windows上,一个简单的解决方法是切换到
托管的\u Windows\u共享的\u内存
而不是
托管的\u共享的\u内存
,您可以解决各种严重的崩溃/挂起问题,而一种崩溃/挂起问题似乎是由Windows文件系统行为和unix文件系统行为之间的差异引起的iour,特别是,在Windows上使用boost和
托管共享内存
,可能会与Windows文件系统锁定限制发生冲突。我被告知boost 1.53已经完成了处理这一问题的工作,但我使用的是boost 1.53,我仍然有这个问题

使用Windows上的常规
托管共享内存
,您可以在任何客户端或服务器应用程序的生命周期之外获得持久性。这在某些人的情况下可能是可取的,因此解决方案对这些人来说不是一个真正的解决方案

然而,在我的例子中,我并不真的需要它,尽管我认为它会很方便,但结果证明它比它的价值更痛苦,至少在Windows上当前的Boost实现中是如此

我还想指出,删除共享内存文件似乎是引发上述问题的竞争条件的根本原因。围绕创建、检查和删除文件的适当同步似乎对系统的实际实现至关重要,尤其是此外,如果您让您的主机(服务器)在某些客户端仍在使用共享内存文件时删除该文件,这似乎是一个灾难性的问题。需要重新启动以清除由此产生的锁定+NTFS文件系统混乱

如果我找到一个真正的解决方案,我会发布它,但是上面的信息比我在任何地方都能找到的更多。请谨记<代码> MauleDySyddLoad ,并考虑使用<代码> MaundsWielsSySyddLoad < /代码>,忘记尝试创建“持久共享内存”。想法有效。相反,只使用非持久性窗口

管理的\u窗口\u共享的\u内存

要解决这个问题,在我的应用程序中保留
managed\u shared\u memory
类可能意味着将对
managed\u shared\u memory
对象的所有访问包装在另一个级别的进程间同步原语中,甚至使用原始Win32 API互斥对象。Boost可以做一些等效的事情,但可能会引入更偶然的复杂性

(旁白:我是这里唯一一个认为模板在一般使用中,尤其是在Boost中,这些天所有东西都做得太过分的人吗?)

更新2:我找到了另一种冻结
托管共享内存的方法,这反过来会冻结您使用它的任何应用程序。我没想到用Boost创建死锁会这么容易,但这很容易。互斥锁c
else if(type == DoOpenOrCreate){
         //This loop is very ugly, but brute force is sometimes better
         //than diplomacy. If someone knows how to open or create a
         //file and know if we have really created it or just open it
         //drop me a e-mail!
         bool completed = false;
         while(!completed){
            try{
               create_device<FileBased>(dev, id, size, perm, file_like_t()); // <-- KABOOM!
               created     = true;
               completed   = true;
            }
            catch(interprocess_exception &ex){
               if(ex.get_error_code() != already_exists_error){
                  throw;
               }
               else{
                  try{
                     DeviceAbstraction tmp(open_only, id, read_write);
                     dev.swap(tmp);
                     created     = false;
                     completed   = true;
                  }
                  catch(interprocess_exception &e){
                     if(e.get_error_code() != not_found_error){
                        throw;
                     }
                  }
                  catch(...){
                     throw;
                  }
               }
            }
            catch(...){
               throw;
            }
            thread_yield();
         }
      }
   boost::interprocess::managed_shared_memory * segment;
   std::pair<MyType*, std::size_t> f = segment->find<MyType>(name);
>   myapp.exe!boost::interprocess::winapi::sched_yield()  Line 998  C++
    myapp.exe!boost::interprocess::ipcdetail::thread_yield()  Line 60 + 0xe bytes   C++
    myapp.exe!boost::interprocess::ipcdetail::spin_mutex::lock()  Line 71   C++
    myapp.exe!boost::interprocess::ipcdetail::spin_recursive_mutex::lock()  Line 91 C++
    myapp.exe!boost::interprocess::interprocess_recursive_mutex::lock()  Line 161   C++
    myapp.exe!boost::interprocess::scoped_lock<boost::interprocess::interprocess_recursive_mutex>::lock()  Line 280 C++
    myapp.exe!boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::priv_get_lock(bool use_lock=true)  Line 1340   C++
    myapp.exe!boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::priv_generic_find<char>(const char * name=0x00394290, boost::interprocess::iset_index<boost::interprocess::ipcdetail::index_config<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0> > > & index={...}, boost::interprocess::ipcdetail::in_place_interface & table={...}, unsigned int & length=1343657312, boost::interprocess::ipcdetail::bool_<1> is_intrusive={...}, bool use_lock=true)  Line 854 + 0x11 bytes  C++
    myapp.exe!boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::priv_find_impl<boost::container::map<AreaKeyType,DATA_AREA_DESC,std::less<AreaKeyType>,boost::interprocess::allocator<std::pair<AreaKeyType const ,DATA_AREA_DESC>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index> > > >(const char * name=0x00394290, bool lock=true)  Line 728 + 0x25 bytes    C++
    myapp.exe!boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::find<boost::container::map<AreaKeyType,DATA_AREA_DESC,std::less<AreaKeyType>,boost::interprocess::allocator<std::pair<AreaKeyType const ,DATA_AREA_DESC>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index> > > >(const char * name=0x00394290)  Line 423 + 0x1e bytes  C++
    myapp.exe!boost::interprocess::ipcdetail::basic_managed_memory_impl<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index,8>::find<boost::container::map<AreaKeyType,DATA_AREA_DESC,std::less<AreaKeyType>,boost::interprocess::allocator<std::pair<AreaKeyType const ,DATA_AREA_DESC>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index> > > >(boost::interprocess::ipcdetail::char_ptr_holder<char> name={...})  Line 346 + 0x23 bytes   C++
    myapp.exe!boost::interprocess::basic_managed_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::find<boost::container::map<AreaKeyType,DATA_AREA_DESC,std::less<AreaKeyType>,boost::interprocess::allocator<std::pair<AreaKeyType const ,DATA_AREA_DESC>,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index> > > >(boost::interprocess::ipcdetail::char_ptr_holder<char> name={...})  Line 208 + 0x10 bytes  C++
    myapp.exe!CCommonMemory::AllocateOrFindAreaMap(const char * name=0x00394290)  Line 128  C++
inline bool shared_memory_object::priv_open_or_create
   (ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm)
{
   m_filename = filename;
   std::string shmfile;
   std::string root_tmp_name;

   //Set accesses
   if (mode != read_write && mode != read_only){
      error_info err = other_error;
      throw interprocess_exception(err);
   }

   switch(type){
      case ipcdetail::DoOpen:
            ipcdetail::get_tmp_base_dir(root_tmp_name);
            shmfile = root_tmp_name;
            shmfile += "/";
            shmfile += filename;
            m_handle = ipcdetail::open_existing_file(shmfile.c_str(), mode, true);
      break;
      case ipcdetail::DoCreate:
            ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, shmfile);
          m_handle = ipcdetail::create_new_file(shmfile.c_str(), mode, perm, true);
      break;
      case ipcdetail::DoOpenOrCreate:
         ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, shmfile);
          m_handle = ipcdetail::create_or_open_file(shmfile.c_str(), mode, perm, true);
      break;
      default:
         {
            error_info err = other_error;
            throw interprocess_exception(err);
         }
   }

   //Check for error
   if(m_handle == ipcdetail::invalid_file()){
      error_info err = system_error_code();
      this->priv_close();
      throw interprocess_exception(err);
   }

   m_mode = mode;
   return true;
}