différence entre strmov et strcpy ?

différence entre strmov et strcpy ? - C - Programmation

Marsh Posté le 29-03-2005 à 02:43:26    

apparemment un strmov fait ca :
 

Code :
  1. char *strmov(register char *dst, register const char *src)
  2. {
  3.    while ((*dst++ = *src++)) ;
  4.    return dst-1;
  5. }


 
quelle différence avec strcpy ? (hormis que strmov fait pointer vers le \0 final)


Message édité par joce le 29-03-2005 à 02:45:42
Reply

Marsh Posté le 29-03-2005 à 02:43:26   

Reply

Marsh Posté le 29-03-2005 à 02:53:20    

"La fonction strmov()  utilisée dans cet exemple est inclue dans la bibliothèque mysqlclient  et fonctionne comme strcpy()  mais retourne un pointeur sur le nul de fin du premier paramètre. Valeur de retour  La longueur de la valeur passée dans to  , n'incluant pas la caractère nul de fin de chaîne."
http://www.nexen.net/docs/mysql/an [...] string.php


Message édité par el muchacho le 29-03-2005 à 02:57:30
Reply

Marsh Posté le 29-03-2005 à 02:56:49    

mais est-ce que src est "déplacé" dans dst en pratique :??:
 
et qu'est ce qui se passe si src est effacé après coup ? (a priori rien ?)
 
Je demande ca aussi par rapport à la version assembler qui semble faire un movb pour chaque caractère
 

Code :
  1. 00045 char *strmov(dst, src)
  2. 00046      char *dst, *src;
  3. 00047 {
  4. 00048   asm("         movl    4(a7),a1        " );
  5. 00049   asm("         movl    8(a7),a0        " );
  6. 00050   asm(".L4:     movb    (a0)+,(a1)+     " );
  7. 00051   asm("         jne     .L4             " );
  8. 00052   asm("         movl    a1,d0           " );
  9. 00053   asm("         subql   #1,d0           " );
  10. 00054 }
  11. 00055


Message édité par joce le 29-03-2005 à 02:57:01
Reply

Marsh Posté le 29-03-2005 à 02:58:07    

J'ai édité mon précédent post.

Reply

Marsh Posté le 29-03-2005 à 03:07:28    

c'est justement dans le cadre de mysql que je m'y interesse :D
 

Code :
  1. void close_temporary_tables(THD *thd)
  2. {
  3.   TABLE *table,*next;
  4.   char *query, *end;
  5.   uint query_buf_size;
  6.   bool found_user_tables = 0;
  7.   if (!thd->temporary_tables)
  8.     return;
  9.   LINT_INIT(end);
  10.   query_buf_size= 50;   // Enough for DROP ... TABLE IF EXISTS
  11.   for (table=thd->temporary_tables ; table ; table=table->next)
  12.     /*
  13.       We are going to add 4 ` around the db/table names, so 1 does not look
  14.       enough; indeed it is enough, because table->key_length is greater (by 8,
  15.       because of server_id and thread_id) than db||table.
  16.     */
  17.     query_buf_size+= table->key_length+1;
  18.   if ((query = alloc_root(thd->mem_root, query_buf_size)))
  19.     // Better add "if exists", in case a RESET MASTER has been done
  20.     end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS " );
  21.   for (table=thd->temporary_tables ; table ; table=next)
  22.   {
  23.     if (query) // we might be out of memory, but this is not fatal
  24.     {
  25.       // skip temporary tables not created directly by the user
  26.       if (table->real_name[0] != '#')
  27.         found_user_tables = 1;
  28.       /*
  29.         Here we assume table_cache_key always starts
  30.         with \0 terminated db name
  31.       */
  32.       end = strxmov(end,"`",table->table_cache_key,"`.`",
  33.                     table->real_name,"`,", NullS);
  34.     }
  35.     next=table->next;
  36.     close_temporary(table);
  37.   }
  38.   if (query && found_user_tables && mysql_bin_log.is_open())
  39.   {
  40.     /* The -1 is to remove last ',' */
  41.     thd->clear_error();
  42.     Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0, FALSE);
  43.     /*
  44.       Imagine the thread had created a temp table, then was doing a SELECT, and
  45.       the SELECT was killed. Then it's not clever to mark the statement above as
  46.       "killed", because it's not really a statement updating data, and there
  47.       are 99.99% chances it will succeed on slave.
  48.       If a real update (one updating a persistent table) was killed on the
  49.       master, then this real update will be logged with error_code=killed,
  50.       rightfully causing the slave to stop.
  51.     */
  52.     qinfo.error_code= 0;
  53.     mysql_bin_log.write(&qinfo);
  54.   }
  55.   thd->temporary_tables=0;
  56. }


 
apparement cette fonction crash dans certains cas, quand un thread se termine et qu'on doit fermer les temp table rattachée à la connexion (et donc marquer DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ... dans le binlog).
 
Me demande si c'est un problème d'estimation de la taille de query_buf_size ou un autre problème
 
Ce qui est bizarre c'est que si dans le thread y a des users temp table et des temp table "internes", il va quand même écrire dans le binlog le DROP TABLE sur la table interne :heink:
C'est louche :o


Message édité par joce le 29-03-2005 à 03:10:53
Reply

Marsh Posté le 29-03-2005 à 09:58:26    

Je doute que ça plante dans le strmov vu que 50 char son alloués au minimum. Par contre je verrais bien un plantage dans le strxmov qui suit.
Le query_buf_size+= table->key_length+1;
alors que strxmov (google) concatène plus de choses, à savoir :
 
#       end = strxmov(end,"`",table->table_cache_key,"`.`",
#                     table->real_name,"`,", NullS);
 
soit 3 caractères, le cache_key et le real_name.
Donc si cette chaine fait moins de 50+table->key_length+1, ça passe, sinon ça casse.
 
Le code correct serait plutôt :
      query_buf_size+= table->key_length + table->real_name_length + 6;
 
avec une longueur initiale de 22 octets (pour le strmov).
Autre chose, le commentaire "// we might be out of memory, but this is not fatal", semblant signifier que alloc_root ne retourne pas forcément la mémoire demandée, auquel cas le strxmov derrière peut se ramasser.
Si c'est le cas, pour moi, ça ferait 2 bugs potentiels à vérifier.
Enfin, en question subsidiaire, vérifier le comportement de strxmov en cas d'overlapping entre src et dst.


Message édité par el muchacho le 01-04-2005 à 09:12:46
Reply

Marsh Posté le 29-03-2005 à 10:52:05    

joce a écrit :

apparemment un strmov fait ca :
 

Code :
  1. char *strmov(register char *dst, register const char *src)
  2. {
  3.    while ((*dst++ = *src++)) ;
  4.    return dst-1;
  5. }


 
quelle différence avec strcpy ? (hormis que strmov fait pointer vers le \0 final)


 
Déjà ce n'est pas tout à fait correct. Si la fonction est vraiment écrite comme ça alors elle va foirer si on l'appelle de cette façon

strmov(ptr + 1, ptr)


Elle recopiera le premier octet de "src" à l'infini.
 
Pour qu'elle fonctionne correctement, elle doit d'abord regarder les positions de "src" et "dst". Si "dst" est placé après "src", elle doit alors balayer "src" à reculon pour que ça marche à 100%. Si "dst" est placé avant "src", alors elle doit balayer "src" normallement.


Message édité par Sve@r le 29-03-2005 à 10:52:53
Reply

Marsh Posté le 29-03-2005 à 11:29:36    

restrict powa

Reply

Marsh Posté le 30-03-2005 à 17:44:24    

Notez que d'apres la description que vous en donnez, strmov fait la meme chose que stpcpy, qui est disponible sur de nombreux systeme (mais ne fais partie d'aucun standard).

Reply

Marsh Posté le 02-04-2005 à 20:01:47    

el muchacho a écrit :

Je doute que ça plante dans le strmov vu que 50 char son alloués au minimum. Par contre je verrais bien un plantage dans le strxmov qui suit.
Le query_buf_size+= table->key_length+1;
alors que strxmov (google) concatène plus de choses, à savoir :
 
#       end = strxmov(end,"`",table->table_cache_key,"`.`",
#                     table->real_name,"`,", NullS);
 
soit 3 caractères, le cache_key et le real_name.
Donc si cette chaine fait moins de 50+table->key_length+1, ça passe, sinon ça casse.
 
Le code correct serait plutôt :
      query_buf_size+= table->key_length + table->real_name_length + 6;
 
avec une longueur initiale de 22 octets (pour le strmov).


 
T'as pas du faire attention au commentaire :
 
#     /*
#       We are going to add 4 ` around the db/table names, so 1 does not look
#       enough; indeed it is enough, because table->key_length is greater (by 8,
#       because of server_id and thread_id) than db||table.
#     */  
 
:)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed