2016-08-19 1 views
1

最近、固有ライブラリを使用していますが、私はこの問題を生のバッファ操作に関して発見しました。生存バッファ付き固有ライブラリに関する1つの問題について質問します

以下のコードでは、入力と出力に9つの整数の2つのローバッファを作成しました。その後、2つの固有行列 in/outを使用して、これらの2つのバッファを固有のマップを使用して新しい配置方法でラップしました。そして、私は単純な転置操作を呼び出しました。しかし、転置操作を呼び出す別の方法は、全く異なる生のバッファ結果につながります。コード1に示すような固有転置関数を直接呼び出すと、結果行列と対応するローバッファの両方の結果が完全に正しいことになります。しかし、コード2に示すように、固有行列を返すカスタマイズされた関数で転置演算をラップすると、問題が発生します。結果行列のみが良いが、生のバッファは壊れているようだ。一部の人はこの問題を知っていますか?これは固有のバグですか?コード1の

コード1つの

#include <iostream> 
#include <Eigen/Dense> 
#include <Eigen/Dense> 

using Eigen::MatrixXi;               


int main() {                  
    int *in;                  
    in = new int[9];                
    for (int i = 0; i < 9; i++)             
    in[i] = i;                 

    int *out;                  
    out = new int[9];                
    for (int i = 0; i < 9; i++)             
    out[i] = 0;                 

    MatrixXi m_in;                 
    m_in.resize(3, 3);                
    new (&m_in) Eigen::Map<MatrixXi>(in, 3, 3);         

    MatrixXi m_out;                
    m_out.resize(3, 3);               
    new (&m_out) Eigen::Map<MatrixXi>(out, 3, 3);         

    m_out = m_in.transpose();              
    std::cout << m_out << std::endl;            
    std::cout << "------------" << std::endl;          
    for (int i = 0; i < 9; i++)             
    std::cout << out[i] << std::endl;           

    return 0;                  
} 

結果:

0 1 2 
3 4 5 
6 7 8 
------------ 
0 
3 
6 
1 
4 
7 
2 
5 
8 

コードコード2の2

#include <iostream> 
#include <Eigen/Dense> 
#include <Eigen/Dense> 

using Eigen::MatrixXi;               

MatrixXi MyTranspose(const MatrixXi &in) {          
    return in.transpose();               
}                    

int main() {                  
    int *in;                  
    in = new int[9];                
    for (int i = 0; i < 9; i++)             
    in[i] = i;                 

    int *out;                  
    out = new int[9];                
    for (int i = 0; i < 9; i++)             
    out[i] = 0;                 

    MatrixXi m_in;                 
    m_in.resize(3, 3);                
    new (&m_in) Eigen::Map<MatrixXi>(in, 3, 3);         

    MatrixXi m_out;                
    m_out.resize(3, 3);               
    new (&m_out) Eigen::Map<MatrixXi>(out, 3, 3);         

    m_out = MyTranspose(m_in);              
    std::cout << m_out << std::endl;            
    std::cout << "------------" << std::endl;          
    for (int i = 0; i < 9; i++)             
    std::cout << out[i] << std::endl;           

    return 0;                  
} 

結果:

0 1 2 
3 4 5 
6 7 8 
------------ 
1028430744 
32644 
1028430744 
32644 
0 
0 
0 
0 
48 
+0

なぜ新しいプレースメントを使用していますか?ローカルオブジェクト 'm_in'と' m_out'を別の型で上書きしますか? 1つはヒープにデータを割り当て、もう1つはスタック上にローカルに配置します。 UB。ちょうどこのようにする 'Eigen :: Map m_in(in、3,3);' – doug

答えて

1

あるオブジェクトを異なるタイプの別のオブジェクトで上書きしています。 m_inは、Eigen::Map<MatrixXi>(in, 3, 3)の内容で上書きされています。新しいプレースメントのターゲットであるためです。 m_inは、inバッファの所有者ではなく、それ以降の操作ではヒープが壊れてしまいます。

MatrixXi m_in;                 
m_in.resize(3, 3);                
new (&m_in) Eigen::Map<MatrixXi>(in, 3, 3); 

することにより、これらの3行(及びM_OUTための同様の行)を交換:これは、ヒープから追加のメモリを割り当てることが、以前にin[]out[]を割り当て使用しないであろう

Eigen::Map<MatrixXi> m_in(in, 3, 3); 

もう1つの問題は、in[]out[]が削除されないことです。プログラムが終了しても問題はありませんが、メモリリークの起こりやすいプログラミングスタイルはお勧めできません。

+0

ありがとう、あなたの答えをありがとう。あなたの答えに関してただ一つの質問。 constを使うと引数がコピーされるのはなぜですか?引数の使用によって引数コピーが回避されるべきではないか? – doody1986

+0

はい、そうです。最初は 'm_in.transpose()'がm_inを修正していて、それをコピーしなければならないと考えていました。そうではない。 transpose()メソッドはデータを変更するのではなく、後でデータを処理して転置操作を行う別の型を返します。したがって、const&は正しい方法です。私は答えのその部分を編集します。 – doug

関連する問題