mickmick57
Messages postés16Date d'inscriptionmardi 18 novembre 2008StatutMembreDernière intervention 3 février 2012
-
30 janv. 2012 à 09:59
mickmick57
Messages postés16Date d'inscriptionmardi 18 novembre 2008StatutMembreDerniè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 ...
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202175 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...
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...
mickmick57
Messages postés16Date d'inscriptionmardi 18 novembre 2008StatutMembreDerniè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?
mickmick57
Messages postés16Date d'inscriptionmardi 18 novembre 2008StatutMembreDerniè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
mickmick57
Messages postés16Date d'inscriptionmardi 18 novembre 2008StatutMembreDerniè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.