Problème avec memcpy et int

Résolu
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012 - 30 janv. 2012 à 09:59
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012 - 3 févr. 2012 à 09:54
Bonjour,

Je m'adresse à vous, car j'ai un problème avec la fonction memcpy et les entiers sur unix. On retrouve un bon nombre de foi le détail de la fonction memcpy sur le net mais très peut de sujet abordant les problème dût à l'architecture.

Voila mon cas,
j'ai une fonction qui permet d'éxecuter des requetes dans une base Sybase et qui utilise la client library.

Cet fonction fonctionne très bien sur une machine 32 bit , par contre sur une 64 bit, il n'y a aucun problème avec les char, par contre mes int sont carrement faux.

Je me tourne vers vous car je ne voit pas la source du problème,
merci d'avance pour votre aide

Voici le code : (je pense que le problème vient de l'endroit ou l'on fait les memcpy/memmove)


int CmdSQL::Execute()
{   // Lancer la commande SQL contenue dans cmd
    // et creer des objets ResultSet
    CS_RETCODE results_ret,ret;
    CS_INT result_type,count;
    CS_DATAFMT *dtfmt = NULL;
    CS_INT *datalength;
    CS_SMALLINT *indicator;
    void **tab = NULL;
    int i;
    bool termine;
    ResultSet *res = NULL;
    char msg[50+1];
    int resultat = 0;
    int resultat2 = 0;


char * memTemp;

    Show("CmdSQL::Execute()");
    Show(txt);
    
    connect->Debug(txt); 
    
    int tries = 0;
    
    do
    {	
    if(ct_send(cmd) != CS_SUCCEED)
    {
        //Error("ct_send() failed");
        connect->Debug("ct_send() failed");
        return -1;
    }
    	while((results_ret ct_results(cmd,&result_type)) CS_SUCCEED)
    	{   switch(result_type)
        {   case CS_ROW_RESULT:
                res = new ResultSet;
                res->connect = connect;
                i = 1;
                termine = false;
                res->nbCols = 0;
                
                // Get number of columns
                if(ct_res_info(cmd,CS_NUMDATA,&res->nbCols,CS_UNUSED,NULL) != CS_SUCCEED)
                {    //Error("ct_res_info() failed");
                    connect->Debug("ct_res_info() failed");
                    return -1;
                }
                
                // Get columns descriptions
                res->datafmt = (CS_DATAFMT**)malloc(res->nbCols * sizeof(CS_DATAFMT*));
                for(int j=1;j<=(res->nbCols);j++)
                {  
                	dtfmt = (CS_DATAFMT*)malloc(sizeof(CS_DATAFMT));
                    if(ct_describe(cmd,j,dtfmt) != CS_SUCCEED)
                    {   //Error("ct_describe() failed");
                    	connect->Debug("ct_describe() failed");
                    	return -1;
                    }
                    res->datafmt[j-1] = dtfmt;                   
                }
                
                datalength = (CS_INT*)malloc(res->nbCols*sizeof(CS_INT));
                indicator = (CS_SMALLINT*)malloc(res->nbCols*sizeof(CS_SMALLINT));
                tab = (void**)calloc(res->nbCols,sizeof(void*));
                
                for(int j=0;j<res->nbCols;j++)
                {   
                	//ConvertType(res->datafmt[j]);
                    tab[j] = (void*)calloc(1,res->datafmt[j]->maxlength);
                    
                    ret = ct_bind(cmd,j+1,res->datafmt[j],tab[j],datalength+j,indicator+j);

memTemp = (char*)malloc(res->datafmt[j]->maxlength);

memTemp = (char*)tab[j];
connect->Debug(String()<<"This data : "<<(char*)memTemp);

                    if(ret != CS_SUCCEED)
                    {    //Error("ct_bind() failed");
                        connect->Debug("ct_bind() failed");
                        return -1;
                    }
                }
                res->res = NULL;
                res->nbLines = 0;          
                                
                while(((ret ct_fetch(cmd,CS_UNUSED,CS_UNUSED,CS_UNUSED,&count)) CS_SUCCEED) || (ret == CS_ROW_FAIL))
                {   if(ret == CS_ROW_FAIL)
                    {   //Error("ct_fetch() failed");
                        connect->Debug("ct_fetch() failed");
                       	return -1;
                    }
                    res->nbLines++;
                    res->res = (void***)realloc(res->res,res->nbLines*sizeof(void**));
                    res->res[res->nbLines-1] = (void**)calloc(res->nbCols,sizeof(void*));
                    
                    
                    for(int j=0;j<res->nbCols;j++)
                    {   
                    	if((res->datafmt[j]->datatype == CS_CHAR_TYPE) /*|| (res->datafmt[j]->datatype == CS_UNICHAR_TYPE)*/)
                    	{
                    		connect->Debug(String()<<"CHAR type from data ");
                    			
                    		res->res[res->nbLines-1][j] = (void*)malloc(datalength[j]+1);
                    		memcpy(res->res[res->nbLines-1][j],tab[j],datalength[j]+1);
                    		((char*)(res->res[res->nbLines-1][j]))[(int)datalength[j]] = '\0';
                    	}
                    	else if(res->datafmt[j]->datatype == CS_UNICHAR_TYPE)
                    	{
                    		connect->Debug(String()<<"UNICHAR type from data ");
                    		
                    		res->res[res->nbLines-1][j] = (void*)malloc(datalength[j]+sizeof(CS_UNICHAR));
                    		memcpy(res->res[res->nbLines-1][j],tab[j],datalength[j]);
                    		((CS_UNICHAR*)(res->res[res->nbLines-1][j]))[(int)datalength[j]/sizeof(CS_UNICHAR)] = 0;
                        }
                    	
                    	
                    	else if(res->datafmt[j]->datatype == CS_INT_TYPE)	//pour les entiers
                    	{
                    		connect->Debug(String()<<"INT type ");	
                    		res->res[res->nbLines-1][j] = calloc(1,sizeof(CS_CHAR)); 
                    		                  		
                    		memcpy(res->res[res->nbLines-1][j],tab[j],sizeof(CS_INT));
                    		((CS_INT*)(res->res[res->nbLines-1][j]))[(int)datalength[j]/sizeof(CS_INT)] = 0;
                        }
                    	
                    	
                    	else if(res->datafmt[j]->datatype == CS_SMALLINT_TYPE)	//pour les smallint
                    	{
                    		connect->Debug(String()<<"SMALLINT type ");
                    		res->res[res->nbLines-1][j] = calloc(1,sizeof(CS_CHAR));
                    		
                    		memcpy(res->res[res->nbLines-1][j],tab[j],sizeof(CS_SMALLINT));
                    		((CS_SMALLINT*)(res->res[res->nbLines-1][j]))[(int)datalength[j]/sizeof(CS_SMALLINT)] = 0;
                        }	                        
                                  
                      //  else
                    //	{	
                   	//		connect->Debug(String()<<"AUTRE type from data ");
                    //		res->res[res->nbLines-1][j] = (void*)calloc(1,datalength[j]);
                     //   	memcpy(res->res[res->nbLines-1][j],tab[j],datalength[j]);
                      //  }
                    }
                }
                for(int j=0;j<res->nbCols;j++)
                {   free(tab[j]);
                }
                free(tab);
                free(datalength);
                free(indicator);
                if(ret == CS_END_DATA)
                {   nbResultSet++;
                    rs = (ResultSet**)realloc(rs,nbResultSet*sizeof(ResultSet*));
                    rs[nbResultSet-1] = res;
                }
                else
                {   //Error("ct_fetch() failed (2)");
                    connect->Debug("ct_fetch() failed (2)");
                    return -1;
                }
                
                break;
            case CS_CMD_SUCCEED:
                //DEBUGFNC("No lines returned");
                break;
            case CS_CMD_FAIL:
                // Error printed by the callback
                resultat = -1;
                break;
            case CS_CMD_DONE:
                break;
            case CS_STATUS_RESULT:
                dtfmt = new CS_DATAFMT;
                dtfmt->datatype = CS_INT_TYPE;
                dtfmt->format = CS_FMT_UNUSED;
                dtfmt->count = 1;
                dtfmt->locale = NULL;
                if(ct_bind(cmd,1,dtfmt,&resultat2,NULL,NULL) != CS_SUCCEED)
                    //Error("ct_bind() failed (2)");
                    connect->Debug("ct_bind() failed (2)");
                if(ct_fetch(cmd,CS_UNUSED,CS_UNUSED,CS_UNUSED,NULL) != CS_SUCCEED)
                    //Error("ct_fetch() failed (3)");
                    connect->Debug("ct_fetch() failed (3)");
                //res->result = resultat;
                ct_fetch(cmd,CS_UNUSED,CS_UNUSED,CS_UNUSED,NULL);
                delete dtfmt;
                if(resultat != -1)	// on donne priorite au resultat de CS_CMD_FAIL
                	resultat = resultat2;
                break;
            default:
                //Error("Unwaited result from ct_results()");
                connect->Debug("Unwaited result from ct_results()");
                break;
        }
    }
}while(connect->GetDeadLockState() && (tries < TRY_ATTEMPT));

    switch(results_ret)
    {   case CS_END_RESULTS:
            break;
        case CS_FAIL:
            //Error("ct_results() failed");
            connect->Debug("ct_results() failed");
            resultat = -1;
            break;
        default:
            //Error("Unwaited result from ct_results() (2)");
            connect->Debug("Unwaited result from ct_results() (2)");
            resultat = -1;
            break;
    }
    connect->Debug(String("Command returned ")<<resultat);
    connect->Debug(String()<<nbResultSet<<" result sets returned");
    for(int r=0;r<nbResultSet;r++)
    {	connect->Debug(String()<<rs[r]->NbLines()<<" lines in result set "<<r);
    	if(connect->LogData())
    		rs[r]->Debug(connect);
    }
    //connect->Debug("--------------------------------------------");
    result = resultat;
    return resultat;
}



note: les CS_INT,CS_CHAR ... ne sont rien d'autre que des int, char ...
A voir également:
  • C++ memcpy
  • Memcpy c++ - Meilleures réponses
  • Memcpy msdn - Meilleures réponses
  • Memcpy msdn - Forum C

16 réponses

Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
30 janv. 2012 à 11:32
en faite, cet ligne met à 0 (ou à la valeur préciser à la fin), les lignes qui sont NULL dans la BDD.


C'est faux... mais bien essayé...

cette ligne est fausse, et dangereuse.
A supprimer.

OUI !
CLAIREMENT !
Cela semble lié au fait que tu joues avec du 32 et du 64 !

Le tout est de trouver où tu t'es planté...

Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
3
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
31 janv. 2012 à 11:19
commence donc par harmoniser ton code, c'est du code mal pensé, plein de copier/coller incomplets

Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
3
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012
1 févr. 2012 à 09:37
Finalement, je suis passé par un pointeur intermédiaire avec lequel je récupère la valeur, puis la copie dans le tableau "res",

en tout cas, je vous remercie encore pour votre aide

R. Mickaël
3
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012
3 févr. 2012 à 09:54
Mince, j'avais plus pensé aux méthodes virtuelles, excusez moi d'avoir posté à la suite d'une discussion clôturé, et merci encore

Mickaël.R
3

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
30 janv. 2012 à 10:29
J'ai juste survollé. Le sujet ne semble pas maitrisé... Le soucis est que tu alloue de la mémoire,n opération loin d'être nodine pour la bonne marche de ton process...


// Get columns descriptions
res->datafmt = (CS_DATAFMT**)malloc(res->nbCols * sizeof(CS_DATAFMT*));
for(int j=1;j<=(res->nbCols);j++) {  
    dtfmt = (CS_DATAFMT*)malloc(sizeof(CS_DATAFMT));
    if(ct_describe(cmd,j,dtfmt) != CS_SUCCEED) {
        //Error("ct_describe() failed");
        connect->Debug("ct_describe() failed");
        return -1;
    }
    res->datafmt[j-1] = dtfmt;                   
}


pourquoi faire un malloc de dtfmt a chaque tour de boucle ?
ne peux tu réutiliser le même pour chaque colonne ?
Pourquoi ne fais tu pas de free de ton dtfmt ?
Vive les fuites mémoire...


memTemp = (char*)malloc(res->datafmt[j]->maxlength);
memTemp = (char*)tab[j];


a Quoi joues tu ?


Ton erreur semble là :
res->res[res->nbLines-1][j] = calloc(1,sizeof(CS_CHAR));
memcpy(res->res[res->nbLines-1][j],tab[j],sizeof(CS_INT));

pourquoi allouer un sizeof(CS_CHAR) ?
n'est-ce pas un peu petit pour stocker ton INT ?




Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
0
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012
30 janv. 2012 à 10:45
Bonjour Renfield,

Tout d'abord je te remercie d'avoir répondu à mon post,
en faite, je vient de reprendre le programme suite à cet erreur, du coup je ne le connais pas encore vraiment,
j'ai vu que dans le programme que des free ont été fait.
je ne peut pas réutiliser le même dtfmt à chaque boucle car il stocke la taille le type de la colonne, la taille ... pour chaque colonne, je m'en ensuite un peut plus loin dans la fonction pour connaitre le type (CS_CHAR, CS_UNICHAR ...)

Désolé pour le "memTemp" je l'avait mis en place pour un petit test car je pensait que c'était un problème du à un pointeur.

Je vais aller voir le bout de code d'on tu m'a parlé et je reviendrais pour dire ce qu'il en et.
Peut il y avoir une raison pour que cela fonctionne en 32 bit et pas en 64 bit?

merci
0
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012
30 janv. 2012 à 11:08
Re,

La fonction me retourne ce résultat :

1|1644972474368|38852274159616|TST2353516|4294967296|17179869184|43383464656896|115964116992|0103|REF 01003|21474836480|N|0|21474836480|0|0|0|1|

au lieu de ces valeurs


1|397|9046|TST2353516|1|4|10101|27|01003|REF 01003|5|O|0|1|0|1|NULL|1

Les types sont: int/int/int/char(10)/int/int/int/int/char(4)/char(10)/int/char(1)/int/int/int/int/int/char(1)

Le premier nombre est un entier et il fonctionne, tout le reste des entiers sont erroné, mais les char/string sont bon
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
30 janv. 2012 à 11:23
1644972474368
donne en hexa :
17F00000000

de la a se dire que ton memcpy est foireux, y'a pas de kilometres...

pas pigé l'interet de :

((CS_INT*)(res->res[res->nbLines-1][j]))[(int)datalength[j]/sizeof(CS_INT)] = 0;

on dirait un copier coller d'une mise a '\0' de la fin d'une chaine de caractères

Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
0
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012
30 janv. 2012 à 11:28
en faite, cet ligne met à 0 (ou à la valeur préciser à la fin), les lignes qui sont NULL dans la BDD.

En faite tab est un tableau de void* qui contient donc des adresses mémoire, du coup on a la première valeur et la longueur de la donné, c'est pour ça que je pense que cela vient de la différence entre la machine 32 et 64
0
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012
30 janv. 2012 à 11:56
re, je suis aller modifier le memcpy

memcpy(res->res[res->nbLines-1][j],tab[j],datalength[j]);


en

memcpy(res->res[res->nbLines-1][j],tab[j],sizeof(int)/2);


il est normal que les valeurs ne sont pas encore les bonnes mais au moins y a du changement,
elles sont toutes a 0
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
30 janv. 2012 à 11:59
pourquoi ce /2 ?

sizeof(int) est il equivalent à sizeof(CS_INT) ?

as tu supprimé la ligne qui met le zero a la suite ?


Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
0
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012
30 janv. 2012 à 17:29
J'ai passer cette ligne en commentaire,

j'ai mis un /2 car ce programme fonctionnait correctement sur une machine 32 bit,
de ce fait, je pensait (en essayant) diviser la taille du int (étant donné que la taille d'un int dépend de l'architecture.
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
30 janv. 2012 à 19:03
"taille d'un int dépend de l'architecture"

Je ne fais pas de UNIX mais ça me semble drolissime.
Fais donc un affichage se sizeof(int) pour vérifier, je suis impatient de savoir.

ciao...
BruNews, MVP VC++
0
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012
31 janv. 2012 à 09:40
Salut,

Dsl j'ai rien dit ("taille d'un int dépend de l'architecture")

Par contre je n'ai pas les même valeur quand j'utilise les sizeof(int) et les CS_INT ( qui devrait être des int appartenant à la client library)
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
1 févr. 2012 à 10:25
Repenser le code, te l'approprier... parfois cela tiens a peu de choses ^^


Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
0
mickmick57 Messages postés 16 Date d'inscription mardi 18 novembre 2008 Statut Membre Dernière intervention 3 février 2012
2 févr. 2012 à 09:26
Bonjour,

J'ai pratiquement fini de résoudre le problème, j'ai juste un petit souci à cause d'une syntaxe que je ne comprend pas très bien, la voila

DbXmlService::DbXmlService(const DbXmlService& serv):XmlService(serv),cmd(serv.cmd)


Les '::' sa je connais, mais je ne connais pas le ':' du coup j'ai du mal a comprendre cet instruction (qui est la définition d'un constructeur)

je vous remercie d'avance pour votre aide

Mickaël.R
0
Rejoignez-nous