Discussione su memcpy [C]

Area di discussione libera.

Moderatore: Staff

Regole del forum
1) Rispettare le idee altrui.
2) Evitare le offese dirette.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Rispondi
Avatar utente
Blizzard
Master
Master
Messaggi: 1509
Iscritto il: mar 2 gen 2007, 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox
Contatta:

Discussione su memcpy [C]

Messaggio da Blizzard »

ciao ragazzi,
volevo aprire questa discussione circa il funzionamento della funzione memcpy.
Stavo scrivendo un piccolo codice per shiftare un array, quando utilizzando la memcpy in una maniera simile

memcpy(a+n,a,3*sizeof(x));

mi sono ritrovato un comportamento simile

{1,2,3,4,5,6,7,8,9} =shift +3 posizioni=> {1,2,3,1,2,3,1,2,3}

insomma... al posto degli ultimi 123 ci dovrebbero essere 4,5,6

Come funziona in pratica la memcpy? fa una copia diretta della memoria?
Sarebbe il solo sistema che spieghi perchè a partire dalla metà della zona di copia i dati siano replicati.

Comunque il codice... e come ho risolto (anche se non mi piace) è accessibile alla fine di questa pagina
http://hackingcoder.blogspot.com/2008/0 ... ifter.html

ciao
Gio

Avatar utente
nuitari
Linux 3.x
Linux 3.x
Messaggi: 777
Iscritto il: dom 14 ott 2007, 12:51
Slackware: 12.0
Località: San Colombano al Lambro
Contatta:

Messaggio da nuitari »

memcpy funziona così:

Codice: Seleziona tutto

void *memcpy(void *dest, const void *src, size_t n);
copia n bytes dall'area di memoria *src all'area di memoria *dest.

Ora, non avendo il tuo codice originale è un po' difficile dire quale sia l'errore, ma a spanne credo tu ti sia sovrascritto i dati da solo, dato che non copiavi i dati in un buffer temporaneo.

Es.:

Supponiamo di avere un array tipo:

Codice: Seleziona tutto

int a[] = {1,2,3,4,5,6,7,8,9};
facendo un

Codice: Seleziona tutto

memcpy(a+2,a,sizeof(int)*4);
tu ti aspetteresti di avere:

{1,2,1,2,3,4,7,8,9}

ed invece ottieni

{1,2,1,2,1,2,7,8,9}

perchè? cosa succede? Succede che memcpy fa un ciclo, e comincia a copiare gli elementi.
Innanzitutto copia a[0] in a[2], per cui avremo:

{1,2,1,4,5,6,7,8,9}

quindi copia a[1] in a[3]

{1,2,1,2,5,6,7,8,9}

quindi copia a[2] in a[4], e qui il dato è stato già sovrascritto, per cui ottieni

{1,2,1,2,1,6,7,8,9}

ed infine, a[3] in a[5]

{1,2,1,2,1,2,7,8,9}

Ed ecco il risultato. Tutto questo lo risolvi passando i dati in un buffer temporaneo.

Avatar utente
Blizzard
Master
Master
Messaggi: 1509
Iscritto il: mar 2 gen 2007, 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox
Contatta:

Messaggio da Blizzard »

ciao,
avevo intuito un simile comportamento... infatti era l'unico modo per spiegarmi la ripetizione dei dati.

Infatti poi ho dovuto necessariamente allocare memoria di appoggio.

Grazie!

ciao
Gio

Avatar utente
rogx
Linux 0.x
Linux 0.x
Messaggi: 38
Iscritto il: lun 24 gen 2005, 0:00

Messaggio da rogx »

Potresti partire dal fondo dell'array, con un ciclo for al contrario:

Codice: Seleziona tutto

#include <stdio.h> 
#include <string.h>

void main(void)
  {
  int myarray[12];
  int a=0;

  // carica l'array con 1, 2, 3, 4, ...
  for (a=0;a<9;a++)
    myarray[a]=a+1;

  // lo scrive a video:
  for (a=0;a<12;a++)
    printf("%d  ", myarray[a]);

  printf("\n");

  // esegue lo shift:
  for (a=6;a>=0;a -= 3)
    memcpy(&myarray[a]+3, &myarray[a], sizeof(int)*3);

  // riscrive l'array a video:
  for (a=0;a<12;a++)
    printf("%d  ", myarray[a]);

  printf("\n");
  }
nota che per non perdere gli ultimi valori l'array e' stato dichiarato piu' lungo di quanto e' il blocco di spostamento (3 nell'esempio)

Ciao, rogx.

Avatar utente
Blizzard
Master
Master
Messaggi: 1509
Iscritto il: mar 2 gen 2007, 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox
Contatta:

Messaggio da Blizzard »

ciao,
capisco la tua soluzione, tuttavia volevo necessariamente effettuare lo shift senza utilizzare cicli :P ma solo con memcpy

Codice: Seleziona tutto

memcpy(&myarray[a]+3, &myarray[a], sizeof(int)*3); 
Questa comunque per l'aritmetica dei puntatori se non sbaglio puoi scriverla come:

Codice: Seleziona tutto

memcpy(a+3,a,sizeof(int)*3);
comunque è una simpatica soluzione...

grazie
Gio

Mario Vanoni
Iper Master
Iper Master
Messaggi: 3174
Iscritto il: lun 3 set 2007, 21:20
Nome Cognome: Mario Vanoni
Slackware: 12.2
Kernel: 3.0.4 statico
Desktop: fluxbox/seamonkey
Località: Cuasso al Monte (VA)

Discussione su memcpy [C]

Messaggio da Mario Vanoni »


Avatar utente
Blizzard
Master
Master
Messaggi: 1509
Iscritto il: mar 2 gen 2007, 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox
Contatta:

Re: Discussione su memcpy [C]

Messaggio da Blizzard »

come al solito Microsoft tenta di costruirsi il suo piccolo "non standard" mondo.
Comunque che la memcpy possa generare buffer overflows sotto opportune disattenzioni non è una novità, specialmente sul lato Microsoft dell'informatica.
Se si troverà una soluzione migliore, soprattutto rispetto alle centinaia di migliaia di software scritte con la memcpy, allora sarà il comitato per lo standard a farcele conoscere.

ciao
Gio

Mario Vanoni
Iper Master
Iper Master
Messaggi: 3174
Iscritto il: lun 3 set 2007, 21:20
Nome Cognome: Mario Vanoni
Slackware: 12.2
Kernel: 3.0.4 statico
Desktop: fluxbox/seamonkey
Località: Cuasso al Monte (VA)

Re: Discussione su memcpy [C]

Messaggio da Mario Vanoni »

Blizzard ha scritto:come al solito Microsoft tenta di costruirsi il suo piccolo "non standard" mondo.
Comunque che la memcpy possa generare buffer overflows sotto opportune disattenzioni non è una novità, specialmente sul lato Microsoft dell'informatica.
Se si troverà una soluzione migliore, soprattutto rispetto alle centinaia di migliaia di software scritte con la memcpy, allora sarà il comitato per lo standard a farcele conoscere.
Giovanni, e` un problema per chi programma nei due ambienti,
M$ rifiuta memcpy, ANSI C e gcc non conoscono memcpy_s,
quindi il poveraccio dovra` mantenere due codici sorgente!

M$ con questo costruisce un "muro di Berlino" per tenersi lontano UNIX/Linux.

Vista la solerzia di ANSI, C89, C99, vecchio in confronto a gcc, icc od ai cc UNIX.

Rispondi