2010-02-13 17 views
5

Delphi utiliza el recuento de referencias con cadenas.Cadenas de Delphi y recuento de referencias

¿Esto significa que solo hay una asignación de memoria para '1234567890' y todas las referencias a, b, c, d, ey f.s?

type 
    TFoo = class 
    s: string; 
    end; 

    const 
    a = '1234567890'; 
    b = a; 
    c : string = a; 

    var 
    d: string; 
    e: string; 
    f: TFoo; 

    function GetStr1(const s: string): string; 
    begin 
    Result := s; 
    end; 

    function GetStr2(s: string): string; 
    begin 
    Result := s; 
    end; 

    begin 
    d := GetStr1(b); 
    e := GetStr2(c); 
    f := TFoo.Create; 
    f.s := a; 
    end; 
+2

(tenga en cuenta que si se habilita el "uso de depuración DCU" se puede rastrear a través de código, ayudantes inclusive) –

Respuesta

9

Sí, solo hay una asignación en su ejemplo específico. Si había usado UniqueString, como dice mghie, o si había construido la cadena de forma dinámica, entonces termina con una nueva asignación de cadena, incluso si el contenido de la cadena es el mismo que cualquier otra cadena.

Sin embargo, un hecho interesante sobre su ejemplo específico: en realidad no hay memoria "asignada" para la cadena '1234567890' en absoluto. Los datos para las constantes de cadena se almacenan en la imagen ejecutable en el disco, y el sistema operativo los busca cuando el código accede. Ocupa espacio de direcciones de memoria, como parte de la asignación en memoria del módulo ejecutable completo, pero como está respaldado por el ejecutable original en el disco, no forma parte de la memoria comprometida del proceso y no necesitará respaldo en el archivo de página.

Por ejemplo, este programa va a reportar una violación de acceso de ejecución:

{$apptype console} 
uses SysUtils; 

const 
    s = '1234567890'; 
procedure Change(const r: string); 
var 
    p: PChar; 
begin 
    p := PChar(r); 
    p^ := 'x'; 
end; 

begin 
    try 
    Change(s); 
    except 
    on e: Exception do 
     Writeln(e.Message); 
    end; 
end. 
+0

Intresting. Debemos tener cuidado al usar punteros. – pKarelian

+0

Si declaro const s: string = '1234567890'; violación de acceso no se plantea? (I no se puede probar ahora) – pKarelian

+1

const s: string = '... no hace diferencia en Delphi 7. El compilador llama a Sistema._LStrLAsg (var dest; const source) que establece el destino apuntando a la const. PERO, si la cadena de destino es GLOBAL, entonces el compilador llama a System._LStrAsg. El código fuente señala que esto se hace para la compatibilidad de DLL. –

5

sí, las cuerdas se cuentan ref, se crea una copia sólo cuando el contenido se modifican a través de una variable (la semántica copia de escritura), más información aquí:

http://www.codexterity.com/delphistrings.htm

+0

buena indirecta. Así que Delphi inteligente no pierde la importancia cuando la función devuelve una cadena. – pKarelian

+0

http://www.codexterity.com/delphistrings.htm "WideString se comporta exactamente como AnsiString; se gestiona automáticamente, termina en nulo y * se cuenta como referencia *" -> ¡WideString NO se contabiliza como referencia! – kibab

+0

https://web.archive.org/web/20100323193851/http://www.codexterity.com/delphistrings.htm está mal? Desde RADStudio "El tipo WideString representa una cadena asignada dinámicamente de caracteres Unicode de 16 bits. En algunos aspectos, es similar a AnsiString. En Win32, WideString es compatible con el tipo COM BSTR. WideString es apropiado para su uso en aplicaciones COM. WideString no se cuenta como referencia, por lo que UnicodeString es más flexible y eficiente en otros tipos de aplicaciones ". – robocat

6

pequeña adición a la answer by jxac:

también se creará una copia cuando UniqueString() se llama en el código, cuando un carácter de la cadena se accede por [], y cuando la cadena se typecasted a 012.380.. Esto sucede incluso cuando el PChar y el elemento de cadena solo se leerán.

Es importante saber cómo forzar una cadena única desde una potencialmente compartida, porque hay funciones de API de Windows que no se deben invocar con un puntero de char de solo lectura, que es PChar a una constante de cadena. En ese caso, la constante necesita ser copiada a una variable primero, por lo que emitirla devolverá un PChar apuntando a la memoria grabable.

+0

Sí. Me di cuenta de que cuando llamé a la función dll con el parámetro PChar que devuelve datos :-( – pKarelian

Cuestiones relacionadas