Problème avec memcpy et int [Résolu]

Messages postés
16
Date d'inscription
mardi 18 novembre 2008
Dernière intervention
3 février 2012
- 30 janv. 2012 à 09:59 - Dernière réponse :
Messages postés
16
Date d'inscription
mardi 18 novembre 2008
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 ...
Afficher la suite 

Votre réponse

16 réponses

Meilleure réponse
Messages postés
17308
Date d'inscription
mercredi 2 janvier 2002
Dernière intervention
22 août 2018
- 30 janv. 2012 à 11:32
3
Merci
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

Merci Renfield 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 87 internautes ce mois-ci

Commenter la réponse de Renfield
Meilleure réponse
Messages postés
17308
Date d'inscription
mercredi 2 janvier 2002
Dernière intervention
22 août 2018
- 31 janv. 2012 à 11:19
3
Merci
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

Merci Renfield 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 87 internautes ce mois-ci

Commenter la réponse de Renfield
Meilleure réponse
Messages postés
16
Date d'inscription
mardi 18 novembre 2008
Dernière intervention
3 février 2012
- 1 févr. 2012 à 09:37
3
Merci
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

Merci mickmick57 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 87 internautes ce mois-ci

Commenter la réponse de mickmick57
Meilleure réponse
Messages postés
16
Date d'inscription
mardi 18 novembre 2008
Dernière intervention
3 février 2012
- 3 févr. 2012 à 09:54
3
Merci
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

Merci mickmick57 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 87 internautes ce mois-ci

Commenter la réponse de mickmick57
Messages postés
17308
Date d'inscription
mercredi 2 janvier 2002
Dernière intervention
22 août 2018
- 30 janv. 2012 à 10:29
0
Merci
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
Commenter la réponse de Renfield
Messages postés
16
Date d'inscription
mardi 18 novembre 2008
Dernière intervention
3 février 2012
- 30 janv. 2012 à 10:45
0
Merci
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
Commenter la réponse de mickmick57
Messages postés
16
Date d'inscription
mardi 18 novembre 2008
Dernière intervention
3 février 2012
- 30 janv. 2012 à 11:08
0
Merci
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
Commenter la réponse de mickmick57
Messages postés
17308
Date d'inscription
mercredi 2 janvier 2002
Dernière intervention
22 août 2018
- 30 janv. 2012 à 11:23
0
Merci
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
Commenter la réponse de Renfield
Messages postés
16
Date d'inscription
mardi 18 novembre 2008
Dernière intervention
3 février 2012
- 30 janv. 2012 à 11:28
0
Merci
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
Commenter la réponse de mickmick57
Messages postés
16
Date d'inscription
mardi 18 novembre 2008
Dernière intervention
3 février 2012
- 30 janv. 2012 à 11:56
0
Merci
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
Commenter la réponse de mickmick57
Messages postés
17308
Date d'inscription
mercredi 2 janvier 2002
Dernière intervention
22 août 2018
- 30 janv. 2012 à 11:59
0
Merci
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
Commenter la réponse de Renfield
Messages postés
16
Date d'inscription
mardi 18 novembre 2008
Dernière intervention
3 février 2012
- 30 janv. 2012 à 17:29
0
Merci
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.
Commenter la réponse de mickmick57
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Dernière intervention
7 novembre 2014
- 30 janv. 2012 à 19:03
0
Merci
"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++
Commenter la réponse de BruNews
Messages postés
16
Date d'inscription
mardi 18 novembre 2008
Dernière intervention
3 février 2012
- 31 janv. 2012 à 09:40
0
Merci
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)
Commenter la réponse de mickmick57
Messages postés
17308
Date d'inscription
mercredi 2 janvier 2002
Dernière intervention
22 août 2018
- 1 févr. 2012 à 10:25
0
Merci
Repenser le code, te l'approprier... parfois cela tiens a peu de choses ^^


Renfield - Admin CodeS-SourceS - MVP Visual Basic & Spécialiste des RegExp
Commenter la réponse de Renfield
Messages postés
16
Date d'inscription
mardi 18 novembre 2008
Dernière intervention
3 février 2012
- 2 févr. 2012 à 09:26
0
Merci
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
Commenter la réponse de mickmick57

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.