| 검색 | ?

strcpy_s에 대해서

1.1. 개요

예전 VisualStudio 버젼에서는 정상적으로 strcpy 표준함수를 사용할수 있었으나 요즘에는 strcpy 를 사용하면 경고를 내보냅니다.
물론 무시할수 있지만 무시하자니 경고누적으로 불안감이 증가하죠...

그래서 울며겨자먹기로 잘 설계된 코드마저도 MS의 강제적인 비표준안으로 코드를 수정해야 합니다.
게다가 이렇게 수정하면 다른운영체제로 포팅할때도 다 수정해주어야 합니다.
참 안좋은 상태만 만들어 가네요.

어쨌건 strcpy, strncpy를 strcpy_s로 바꾸는 작업을 할수밖에 없는데
문제는 기존 코드를 아무생각없이 바꾸었다가는 낭패를 볼수 있습니다.
그래서 정리합니다. strcpy_s와 strncpy는 같은 치환레벨이 아니라는 점을 말입니다.

strncpy로 된 부분을 strcpy_s 로 치환하기 위해서는 크게 문제시 되는것은 두가지 입니다.

하나는 인자의 위치가 다르다는 점이고 또 다른 하나는 Source에 주어지는 문자열이 반드시 Null terminate되어야 한다는 점입니다.
Null terminate되지 않은 경우 일부 Window version에서는 예외가 발생되는데 또 어떤 버젼에서는 잘 돌아간다는 점입니다.
strcpy_s 와 strncpy함수는 동일한 목적의 함수가 아니라는 점을 인지해야 합니다.

1.2. strcpy_s

  1. Destination의 null terminate를 보장해준다.
  2. Source 는 반드시 null terminate해주어야 한다. 그렇지 않으면 동작이 보장되지 않는다.
  3. Size를 0 또는 그보다 작은크기대역으로 주면 error를 반환한다.
  4. Destination과 Source의 메모리 영역이 겹치면 의도하지 않는 동작이 일어날수 있다.
  5. Destination과 Source는 어느한쪽이라도 NULL이면 error를 반환한다.
  6. multi-byte지원한다.
  7. 구현은 다음과 같거나 유사한 행동을 할것이다.

    errno_t strcpy_s(char *d, size_t dn, const char *s)
    {
        size_t cn;
        size_t c;
    
        if(d == NULL || s == NULL) {
            return(EINVAL);
        }
        if(dn <= ((size_t)0u)) {
            return(ERANGE);
        }
        --dn;
    
        cn = strlen(s /* s가 null terminate되지 않으면 동작이 보장되지 못한다. */);
        cn = (dn <= cn) ? dn : cn;
    
        for(c = 0;c < cn;c++) { d[c] = s[c]; }
        d[c] = '\0'; /* null terminate 보장 */
    
        return 0;
    }
    

1.3. strncpy

  1. Destination의 null terminate를 보장하지 않는다.
  2. Source는 null terminate가 아닌 경우도 허용한다. 그렇지만 이 경우 Size보다 Source공간이 적은 경우 동작이 보장될수 없다.
  3. Size가 0인 경우도 허용한다. 이 경우 아무 동작도 안한다.
  4. Destination과 Source의 메모리 영역이 겹치면 의도하지 않는 동작이 일어날수 있다.
  5. Destination과 Source는 어느한쪽이라도 NULL이면 동작을 보장할수 없다.
  6. multi-byte 에 대한 고려는 정의하지 않는다.
  7. 구현은 다음과 같거나 동등한 행동을 할것이다.

    char *strncpy(char *d, const char *s, size_t dn)
    {
        size_t c;
    
        /* d 와 s중 하나라도 NULL인 경우 어떤일이 벌어질지 정의되지 않는다. */
    
        for(c = 0;c < dn && s[c] != '\0';c++) { d[c] = s[c]; }
        for(;c < dn;c++) { d[c] = '\0'; }
    
        return d;
    }
    

1.4. strlcpy

  1. Destination의 null terminate를 보장해준다.
  2. Source 는 반드시 null terminate해주어야 한다. 그렇지 않으면 동작이 보장되지 않는다.
  3. Destination과 Source의 메모리 영역이 겹치면 의도하지 않는 동작이 일어날수 있다.
  4. multi-byte 에 대한 고려는 정의하지 않는다.
  5. Source 문자열의 길이를 반환한다.
    • Destination 보다 반환 값(Source)이 큰 경우 복사된 문자열은 잘린 형태가 된다는 의미
  6. 구현은 다음과 같거나 유사한 행동을 할것이다. (참고: [https]https://man.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3[])
    size_t strlcpy(char *d, const char *s, size_t dn)
    {
        size_t sl = strlen(s /* s가 null terminate되지 않으면 동작이 보장되지 못한다. */);
        size_t cn, c;
    
        if (dn-- > 0) {
            cn = (dn <= sl) ? dn : sl;
    
            for(c = 0;c < cn;c++) { d[c] = s[c]; }
            d[c] = '\0'; /* null terminate 보장 */
        }
    
        return sl;
    }
    


Copyright ⓒ MINZKN.COM
All Rights Reserved.