1

void* を受け入れる C 関数で shared_ptr を渡したいです。shared_ptr で作成されたオブジェクトが破棄されるのは安全で、いつ破棄できますか? お気に入り、

class CBar
{
 public:
    CBar(){}
    ~CBar(){}
    void lock(){}
    void unlock(){}
};

//----------------------------------------------------

typedef struct element
{
   std::string filename;
   void (*cb)(std::string filename, void* data);
   void* data;
};

std::list<element> elm;

void reg(std::string filename, void (*cb)(std::string filename, void*data), void* data)
{
    element item;
    item.filename = filename;
    item.cb = cb;
    item.data = data;
}

void unreg(std::string filename)
{
   std::list<elements>::iter;
   for(iter=elm.begin();iter!=elm.end();++iter)
   {
      if((*iter).filename == filename)
      {
         elm.erase(iter);
         break;
      }
   }
}

void exec()
{
    std::list<element>::iterator iter;
    for(iter=elm.begin();iter!=elm.end();++iter)
    {
        (*iter).cb((*iter).filename,(*iter).data);
    }
}

//---------------------------------------------------
// in another source file

void cb(std::string filename, void* data)
{
   boost::shared_ptr<CBar> cbar = *(boost::shared_ptr<CBar>*)(data);
   cbar->lock();
}

void foo(std::string filename)
{
    //create the shared_ptr here.
    boost::shared_ptr<CBar> ffoo(new CBar);

    //then pass the shared_ptr object
    reg(filename, &cb, &ffoo);

}

int main()
{
   foo("file");
   exec();

   return 0;
}
4

1 に答える 1

1

関数がスコープを離れると、共有ポインターは破棄されます。それがそのデータをラップする最後のものである場合、データも一緒に移動します (したがって、リスト内のストレージも偽物になります)。ローカル変数のアドレスを送信しているため、サンプルは二重に悪化します。これは、reg()関数が終了し、ローカル変数がスコープ外になると、完全に未定義の動作になります

要素構造体にも共有ポインターを配置することをお勧めします。結局のところ、共有されているため、要素が削除されるまでそのデータの寿命が延びます。これが真の C タイプのコールバックである場合は、最初のコールバック パラメータを aにして、それに応じてメソッドconst char*を送信することもできます。c_str()

注: ブーストをインストールしていないため、以下のコードでは を使用していますstd::shared_ptr<>が、セマンティクスは同じである必要があります。

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <memory>
#include <cstdlib>

class CBar
{
public:
    CBar(){}
    ~CBar(){}
    void lock(){}
    void unlock(){}
};

struct element
{
    std::string filename;
    void (*cb)(std::string, void* data);
    std::shared_ptr<CBar> data;
};


std::list<element> elm;

void reg(std::string filename,
         void (*cb)(std::string, void*),
         std::shared_ptr<CBar>& data)
{
    element item;
    item.filename = filename;
    item.cb = cb;
    item.data = data;
    elm.push_back(item);
}

void exec()
{
    std::list<element>::iterator iter;
    for(iter=elm.begin();iter!=elm.end();++iter)
    {
        iter->cb(iter->filename, iter->data.get());
    }
}

// in another source file
void cb(std::string filename, void* data)
{
    CBar *cbar = static_cast<CBar*>(data);
    cbar->lock();
}

void foo(std::string filename)
{
    //create the shared_ptr here.
    std::shared_ptr<CBar> ffoo(new CBar);

    //then pass the shared_ptr object
    reg(filename, &cb, ffoo);

}

int main()
{
    foo("file");
    exec();
    return 0;
}
于 2013-09-21T09:11:11.717 に答える