2017-03-07 1 views
-1

J'ai un comportement étrange avec le code suivant en utilisant la bibliothèque Eigen.La valeur du pointeur de retour change après la transmission d'une méthode

Si j'attribue le pointeur à DoubleListCg->doubles, la valeur obtenue pour le DoubleListCg->doubles[i] est erronée. Mais si j'attribue l'élément un par un, alors la valeur obtenue pour le tableau de pointeurs ci-dessus est correcte. Pourquoi?

Ceci est mon code ci-dessous:

#define DllExport __declspec(dllexport) 

#include "stdafx.h" 
#define EIGEN_USE_MKL_ALL 
#include <iostream> 
#include "Eigen/Dense" 
#include "Eigen/src/Core/util/MKL_support.h" 
#include <Eigen/Sparse> 
#include <Eigen/Eigenvalues> 
#include <vector> 
#include <Eigen/PardisoSupport> 
using namespace std; 
using namespace Eigen; 

extern "C" struct DllExport DoubleListCg 
{ 
    int num_points; 
    double* doubles; 
}; 

// working 
void DoubleList(VectorXd vector, DoubleListCg *dListPtr) 
{ 
    dListPtr->num_points = vector.size(); 
    dListPtr->doubles= (double*) malloc (dListPtr->num_points*sizeof(double)); 
    for (int i = 0; i < vector.size(); i++) 
    { 
     dListPtr->doubles[i]=vector[i]; 
    }  

} 

//not working 
void DoubleList2(VectorXd vector, DoubleListCg *dList) 
{ 
    dList->num_points = vector.size(); 
    dList->doubles =vector.data(); 

} 

void VectorConvert() 
{ 
    VectorXd vector(3); 
    vector<<1,2,3; 

    DoubleListCg dList; 
    DoubleList(vector, &dList); //this works; the dList gets the right values at first element 

    DoubleListCg dList2; 
    DoubleList2(vector, &dList2) //this doesn't work; the dList2 gets the wrong values at first element 


} 

Il doit être quelque chose de vraiment élémentaire que je raccroche.

question connexe: Y at-il de toute façon que je peux pointer dList->doubles au vector.data()? Je ne veux pas tout copier encore et encore

+0

Pourquoi cette question a été downvoted et voté pour la fermeture (pour la raison de ne pas reproductible)? – Graviton

Répondre

3
//not working 
void DoubleList2(VectorXd vector, DoubleListCg *dList) 
{ 
    dList->num_points = vector.size(); 
    dList->doubles =vector.data(); 
} 

En fonction ci-dessus vector est variable locale pour fonctionner DoubleList2. Lorsque la fonction retourne ou est complétée alors cette variable locale est détruite et dList->doubles devient un pointeur pendante et il conduit à un comportement indéfini si un tel pointeur dangling est accédé.

mise en œuvre correcte serait:

void DoubleList2(VectorXd vector, DoubleListCg *dList) 
{ 
    dList->num_points = vector.size(); 
    dList->doubles = (double*) malloc (dList->num_points*sizeof(double)); 
    memcpy(dList->doubles, vector.data(), dList->num_points*sizeof(double)); 
} 
+0

Y at-il de toute façon que je puisse pointer 'dList-> doubles' à' vector.data() '? Je ne veux pas tout copier encore et encore – Graviton

+0

Utilisez le vecteur par référence comme suggéré par @Avi Ginsburg. la durée de vie du vecteur est valide à la p dentelle d'accès 'dList-> double'. – sameerkn

+0

Votre implémentation correcte n'est-elle pas une copie de toutes les données de 'vector.data()' à 'dList-> doubles'? – Graviton

3

Dans void DoubleList(VectorXd vector, DoubleListCg *dListPtr)vector est une copie (temporaire) de l'argument. Lorsque vous allouez de la mémoire, puis copiez les valeurs, elles sont conservées dans dListPtr. Dans le cas ne fonctionnant pas, le pointeur .data() pointe vers un tableau temporairement alloué. Quand il est hors de portée, la mémoire n'est pas garantie de rester alloué. Si vous transmettez vector par référence, la mémoire reste allouée jusqu'à ce que l'original soit hors de portée.

+0

Je vois. Y at-il de toute façon que je peux pointer directement le 'dList-> double' à' vector.data() '? Je ne veux pas tout copier encore et encore – Graviton

+0

Vous pouvez le passer par référence ('DoubleList (VectorXd & vector ...'). Notez simplement que cela ne fonctionnera pas si vous passez une expression à 'DoubleList', c'est-à-dire 'DoubleList (3.0 * vec ...)'. –

+0

Désolé, que voulez-vous dire par passer une expression à 'DoubleList'? – Graviton