데이터 형식 - 문자열

문자열 의 데이터 구 조 는 비교적 간단 하고 관련 된 것 이 비교적 적 습 니 다. 저 는 소스 코드 의 데이터 구조의 정 의 를 간단하게 보 여 드 리 겠 습 니 다.
Zend_string 데이터 구조
typedef struct _zend_string zend_string;


struct _zend_string {
zend_refcounted_h gc;
zend_ulong h; /* hash value */
size_t len;
char val[1];
};

이 구 조 는 네 명의 구성원 이 있다.
  • gc : zend_refcounted_h 구조 체, 주로 변수의 인용 계수 로 메모리 관리 에 사용 되 며, 후속 메모리 관리 에 사 용 됩 니 다
  • h: 문자열 의 Hash Code (time 33 Hash 알고리즘 을 사용 하여 얻 은 Hash 값) 는 문자열 이 배열 의 key 로 사 용 될 때 초기 화 되 며, 같은 문자열 이 key 로 여러 번 사용 되면 중복 계산 되 지 않 습 니 다.
  • len: 문자열 길이
  • val: 문자열 내용 을 저장 하기 위 한 가 변 배열메모리 할당 시 string 형식 코드
  • 를 살 펴 보 겠 습 니 다.
    //file zend_string.c
    
    
    static zend_always_inline zend_string *zend_string_alloc(size_t len, int persistent)
    {
       zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)), persistent);
       ....
       //          
       zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(XtOffsetOf(zend_string, val) + len + 1), persistent); //      1     c  \0     
    }

    문자열 의 바 이 너 리 보안
    C 언어 를 배 운 사람 은 알 아야 한다. 문자열 에 마지막 문 자 를 제외 하고 \0 가 포함 되 어 있 으 면 안 된다. 그렇지 않 으 면 문자열 의 끝 문자 로 여 겨 지기 때문에 C 언어의 문자열 에 많은 제한 이 있다. 예 를 들 어 그림, 파일 등 바 이 너 리 데 이 터 를 저장 하지 않 는 다.그러나 PHP 는 이러한 제한 이 없습니다. 문자열 은 바 이 너 리 데 이 터 를 저장 할 수 있 고 오류 가 발생 하지 않 습 니 다. PHP 의 이러한 능력 을 문자열 의 바 이 너 리 보안 이 라 고 합 니 다.
    C 코드:
    char a[] = "aaa\0b";
    int len = strlen(a);
    printf("%d
    ", len); // 3

     
    PHP 코드:
    $a = "aaa\0b";
    echo strlen($a).PHP_EOL; //5

    급속 충전기 ~: 그런데 PHP 는 C 언어 로 쓰 여 있 지 않 나 요?왜 PHP 가 틀 리 지 않 습 니까?다시 한 번 zendstring 구조 체, 멤버 변수 len 기억 나 세 요?이것 은 바 이 너 리 보안 을 실현 하 는 관건 입 니 다. 우 리 는 C 처럼 \0 문자열 이 읽 혔 는 지 여 부 를 판단 하지 않 고 길이 len 을 통 해 문자열 의 바 이 너 리 안전 을 보장 합 니 다.
  • 여기 포 인 트 를 먼저 긋 고 칠판 을 두 드 려 라!우리 의 후속 배열 등 복잡 한 유형의 설명 은 모두 HashTable 에 의존 하여 이 루어 집 니 다. HashTable 을 사용 하 는 것 이 비교적 중요 한 것 은 Hash 함 수 를 선택 하여 Hash 충돌 을 최소 화하 고 PHP 는 실현 방식 Time 33 알고리즘 을 선택 하 는 것 입 니 다.
  • Time 33 알고리즘 에 대하 여: 현재 문자열 Hash 에 가장 좋 은 해시 알고리즘 중 하나 입 니 다. 이 알고리즘 은 속도 가 매우 빠 르 고 분류 가 매우 좋 기 때 문 입 니 다 (충돌 이 적 으 며 분포 가 균일 합 니 다).
  • 제 가 본 PHP 소스 코드 의 버 전과 새 형 이 다 르 기 때문에 Time 33 알고리즘 이 실 현 된 위치 도 약간 다 릅 니 다. 관심 이 있 는 친구 에 게 저 는 해당 하 는 소스 코드 위치
    //file : zend_string.h
    
    
    static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size_t len)
    {
       register zend_ulong hash = Z_UL(5381);
    
       /* variant with the hash unrolled eight times */
       for (; len >= 8; len -= 8) {
          hash = ((hash << 5) + hash) + *str++;
          hash = ((hash << 5) + hash) + *str++;
          hash = ((hash << 5) + hash) + *str++;
          hash = ((hash << 5) + hash) + *str++;
          hash = ((hash << 5) + hash) + *str++;
          hash = ((hash << 5) + hash) + *str++;
          hash = ((hash << 5) + hash) + *str++;
          hash = ((hash << 5) + hash) + *str++;
       }
       switch (len) {
          case 7: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
          case 6: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
          case 5: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
          case 4: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
          case 3: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
          case 2: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */
          case 1: hash = ((hash << 5) + hash) + *str++; break;
          case 0: break;
    	EMPTY_SWITCH_DEFAULT_CASE()
       }
        /* Hash value can't be zero, so we always set the high bit */
    	#if SIZEOF_ZEND_LONG == 8
       	return hash | Z_UL(0x8000000000000000);
    	#elif SIZEOF_ZEND_LONG == 4
        return hash | Z_UL(0x80000000);
    	#else
    	# error "Unknown SIZEOF_ZEND_LONG"
    	#endif
    }
    를 붙 였 습 니 다. 
  • 좋은 웹페이지 즐겨찾기