C Language Copia della memoria sovrapposta


Esempio

Un'ampia varietà di funzioni di libreria standard hanno tra i loro effetti la copia di sequenze di byte da una regione di memoria a un'altra. La maggior parte di queste funzioni ha un comportamento non definito quando le regioni di origine e di destinazione si sovrappongono.

Ad esempio, questo ...

#include <string.h> /* for memcpy() */

char str[19] = "This is an example";
memcpy(str + 7, str, 10);

... tenta di copiare 10 byte in cui le aree di memoria di origine e destinazione si sovrappongono di tre byte. Per visualizzare:

               overlapping area
               |
               _ _
              |   |
              v   v
T h i s   i s   a n   e x a m p l e \0
^             ^
|             |
|             destination
|
source

A causa della sovrapposizione, il comportamento risultante non è definito.

Tra le funzioni di libreria standard con una limitazione di questo tipo sono memcpy() , strcpy() , strcat() , sprintf() e sscanf() . Lo standard dice di queste e di molte altre funzioni:

Se la copia avviene tra oggetti che si sovrappongono, il comportamento non è definito.

La funzione memmove() è l'eccezione principale a questa regola. La sua definizione specifica che la funzione si comporta come se i dati di origine fossero stati prima copiati in un buffer temporaneo e quindi scritti nell'indirizzo di destinazione. Non ci sono eccezioni per la sovrapposizione di regioni di origine e destinazione, né alcuna necessità per una, quindi memmove() ha un comportamento ben definito in questi casi.

La distinzione riflette un'efficienza vs. compromesso di generalità. La copia di tali funzioni si verifica in genere tra regioni disgiunte della memoria e spesso è possibile sapere al momento dello sviluppo se una determinata istanza di copia della memoria si troverà in quella categoria. Supponendo che la non sovrapposizione offra implementazioni relativamente più efficienti che non producono in modo affidabile risultati corretti quando l'ipotesi non regge. La maggior parte delle funzioni della libreria C è permessa le implementazioni più efficienti e memmove() riempie gli spazi vuoti, servendo i casi in cui l'origine e la destinazione possono o si sovrappongono. Tuttavia, per produrre l'effetto corretto in tutti i casi, è necessario eseguire ulteriori test e / o impiegare un'implementazione relativamente meno efficiente.