2014-01-05 11 views
0

파스칼 문자열은 메모리에 어떻게 배치됩니까?파스칼 문자열은 메모리에서 어떻게 표현됩니까?

읽음 : http://www.freepascal.org/docs-html/ref/refsu12.html 문자열은 힙에 저장되고 참조 횟수가 계산됩니다. 길이와 참조가 저장된 위치를 파악하기 위해, 나는 문자열을 만들어 그 위에 많은 테스트를했다 :

type PInt = ^Integer; 

var 
    str: String; 
begin 
    str := 'hello'; 
    writeln(PInt(@str[1]) - (sizeof(integer) * 1)); //length 
    writeln(PInt(@str[1]) - (sizeof(integer) * 2)); //reference count 
end. 

첫 번째는 길이를 출력하고 두 번째는 참조 카운트를 출력합니다. 이것은 완벽하게 훌륭하게 작동하며 작동합니다.

은 지금은 C에서 같은 일을 모방하려 :

다음
Export char* NewCString() 
{ 
    const char* hello_ptr = "hello"; 

    int length = strlen(hello_ptr); 

    //allocate space on the heap for: sizeof(refcount) + sizeof(int) + strlength 
    char* pascal_string = (char*)malloc((sizeof(int) * 2) + length); 

    *((int*)&pascal_string[0]) = 0; //reference count to 0. 
    *((int*)&pascal_string[sizeof(int)]) = length; //length of the string. 

    strcpy(&pascal_string[sizeof(int) * 2], hello_ptr); //copy hello to the pascal string. 

    return &pascal_string[sizeof(int) * 2]; //return a pointer to the data. 
} 

Export void FreeCString(char* &ptr) 
{ 
    int data_offset = sizeof(int) * 2; 
    free(ptr - data_offset); 
    ptr = NULL; 
} 

파스칼에서 내가 할 :

var 
    str: string; 
begin 
    str := string(NewCString()); 
    writeln(PInt(@str[1]) - (sizeof(integer) * 1)); //length - prints 5. correct. 
    writeln(PInt(@str[1]) - (sizeof(integer) * 2)); //reference count - prints 1! correct. 
    //FreeCString(str); //works fine if I call this.. 
end. 

파스칼 코드가 제대로 길이를 인쇄하고 참조 카운트가 1 씩 증가 임무 때문에. 이 말이 맞습니다.

그러나 실행이 끝나 자마자 심하게 충돌합니다! 문자열/힙을 해제하려고 시도하는 것 같습니다. FreeCString을 직접 호출하면 잘 작동합니다! 무슨 일이 일어나고 있는지 잘 모르겠습니다.

크래시가 발생하는 이유는 무엇입니까?

+3

여러 버전의 Pascal (Wirth/Turbo Pascal은 바이트 0으로 정의 된 길이, Delphi 2가 도입 한 긴 문자열은 모두 'ShortString'으로 선언하지 않는 한 혼란 스럽습니다.)을 혼란스럽게합니다. 태그에 네 가지 언어가 나열되어 있습니다. 대신, 처음에 실제로 달성하려는 내용을 설명하고 어떻게 수행하는지 질문하는 것이 어떻습니까? 왜 부숴 지느냐하는 것은 당신이 올바르지 않은 것에 대해 잘못된 가정을하고 있기 때문입니다. –

+0

있습니다. 나는 언어를 좁혔다. 매개 변수로 길이를 전달하지 않고도 파스칼 문자열로 C 스타일 문자열을 변환하려고합니다. – Brandon

+0

"c-stype 문자열을 파스칼 문자열로 변환하려고합니다"는 의미는 무엇입니까? Delphi/Free Pascal은 길이 매개 변수없이 null로 끝나는 C 스타일 문자열을 완벽하게 수용 할 수 있습니다. WinAPI 호출을 통해 모든 단일 Windows 응용 프로그램에서 수천 번 수행됩니다. 다시 한번, 당신은 실제로 무엇을 성취하려고합니까? –

답변

0

런타임 시스템이 문자열을 메모리에 특정 방식으로 배치했기 때문에 C 코드를 작성하여 해당 메모리 레이아웃을 복제 할 수 있다는 의미는 아닙니다. 문자열 관리에는 추가 제약 조건 또는 외부 데이터 구조가 포함될 수 있습니다. FreePascal과 호환되는 문자열을 만들려면 FreePascal의 자체 라이브러리 루틴을 사용하십시오.

RefPount가 0이 될 때 FreePascal이 free() 외의 다른 것을 요구하지만, 리버스 엔지니어링을하지 않거나 ABI 사양을 파헤 치지 않고도 무엇을 말할 수없는 것 같습니다.

1
  1. 은 "문자열"를 AnsiString과 유니 코드 스트링이 레이아웃 델파이 2007 동일 FPC 2.6 FPC의 2.7.x + (가는 변경된
  2. 3 개 개의 문자열 타입 (ShortString은, AnsiString을하고 유니 코드 스트링)을 가리킬 수 별칭 Delphi 2009)
  3. Delphi mem allocator는 할당 된 블록의 크기를 알 수 있어야합니다. 일반적으로이 작업은 블록에 32 비트 크기를 넣음으로써 수행됩니다.
  4. FreePascal과 Delphi에는 플러그 가능 메모리 할당자가 있습니다. 기본 Free Pascal 관리자는 자체 하위 할당 자입니다. libc에서 사용하는 모든 것을 (on * nix에서) 사용하려면 주 프로그램에서 unit cmem을 첫 번째 단위로 사용하십시오.
  5. ansistring 및 unicodestring을 다시 계산하면 수동 트릭을 사용하여 참조 횟수의 무결성을 유지 관리해야합니다. 여기에는 Pascal < -> C 변환을 위해 파스칼 ABI를 유지 보수하는 것이 포함됩니다. 짧은 에서

하지를 수행하고, 그 통해 생성자와 파스칼하는 소멸자 기능을 추가하고 모든 할당을 수행해야합니다 드문 경우.

p.s. rtl/inc/astrings.inc P.s.2 Windows에서 interlanguage 문자열 유형에 대해 COM 호환 widestring (BSTR)을 사용하는 것이 가장 쉽습니다.

+0

참조 횟수를 -1로 변경하여 문제를 해결했습니다. 파스칼을 만드는 것은 문자열이 일정하다고 생각합니다. 따라서 결코 내 문자열을 "자유롭게"하려고 시도하지 않으며 나 자신을 처리합니다. 이제 잘 작동합니다. 네가 한 말을 해 볼게. – Brandon

관련 문제