strdup ()-C에서 무엇을합니까?


302

strdup()C 에서 함수 의 목적은 무엇입니까 ?


44
strduup ()과 유사한 멋진 함수 인 strdupa () (GNU C 라이브러리에 있음)도 있지만 스택에 메모리를 할당합니다. strdup ()과 같이 프로그램에서 메모리를 명시 적으로 해제 할 필요는 없습니다. strdupa ()가 호출 된 함수를 종료하면 자동으로 해제됩니다.
dmityugov

11
strdupastrlen매우 작고 이미 결정하지 않은 한 위험합니다 . 그러나 스택에서 고정 크기 배열을 사용할 수 있습니다.
R .. GitHub 중지 지원 아이스

4
@slacker Google 번역이 도움이되지 않습니다 ... 폴란드어에서 strdup/ strdupa의미는 무엇입니까 ?
haneefmubarak

14
@haneefmubarak 여기에
anatolyg

여기에서는 StrDup과의 strcpy 간의 차이 stackoverflow.com/questions/14020380/strcpy-vs-strdup는
시바 Prakash는

답변:


372

C와 UNIX가 단어를 할당하는 약식에 익숙하다고 가정하면 문자열복제합니다 :-)

실제로 ISO C 표준 자체 (a) (POSIX 일)의 일부가 아니라는 점에서 다음 코드와 효과적으로 동일하게 작동합니다.

char *strdup(const char *src) {
    char *dst = malloc(strlen (src) + 1);  // Space for length plus nul
    if (dst == NULL) return NULL;          // No memory
    strcpy(dst, src);                      // Copy the characters
    return dst;                            // Return the new string
}

다시 말해:

  1. 이전 문자열을 보유하기에 충분한 메모리를 할당하려고 시도합니다 (문자열의 끝을 표시하기 위해 '\ 0'문자 포함).

  2. 할당이 실패하면로 설정 errno되어 ENOMEM반환됩니다.NULL 즉시 됩니다. 의 설정 errno을하는 것은 ENOMEM뭔가가 malloc우리가 명시 적으로 우리에 할 필요가 없습니다 POSIX에 않습니다 strdup. POSIX 호환 이 아닌 경우 ISO C는 실제로 존재를 요구하지 않으므로 ENOMEM여기에 포함시키지 않았습니다 (b) .

  3. 그렇지 않으면 할당이 작동하여 이전 문자열을 새 문자열 (c)에 복사하고 새 주소 (호출자가 어떤 시점에서 해제해야 함 ) 를 반환합니다.

그것이 개념적인 정의라는 것을 명심하십시오. 급여를받을 가치가있는 모든 라이브러리 작성자는 사용중인 특정 프로세서를 대상으로 최적화 된 코드를 제공했을 수 있습니다.


(a) 단, str소문자로 시작하는 기능 은 향후 지침을 위해 표준으로 예약되어 있습니다. 보낸 사람 C11 7.1.3 Reserved identifiers:

각 헤더는 관련 하위 조항에 나열된 모든 식별자를 선언 또는 정의하고 * 선택적으로 관련 미래 라이브러리 지침 하위 조항에 나열된 식별자를 선언 또는 정의합니다. **

향후 방향은 다음에서 string.h확인할 수 있습니다 C11 7.31.13 String handling <string.h>.

로 시작하는 함수 이름 str, mem또는 wcs와 소문자 편지는의 선언에 추가 할 수있다 <string.h>헤더.

따라서 안전을 원한다면 다른 것으로 부를 것입니다.


(b) 변경 사항은 기본적으로 다음으로 대체 if (d == NULL) return NULL;됩니다.

if (d == NULL) {
    errno = ENOMEM;
    return NULL;
}

(씨) 내가 사용하는 것에 주목strcpy 의도를 분명히 보여주기 때문에 . 일부 구현에서는 memcpy데이터를 더 큰 청크로 또는 병렬로 전송할 수 있으므로 사용하는 것이 더 빠를 수 있습니다 (이미 길이를 알고 있기 때문에) . 또는 :-) 최적화 지침 # 1 : "측정, 추측하지 마십시오".

어쨌든 그 길을 가기로 결정하면 다음과 같은 일을 할 것입니다.

char *strdup(const char *src) {
    size_t len = strlen(src) + 1;       // String plus '\0'
    char *dst = malloc(len);            // Allocate space
    if (dst == NULL) return NULL;       // No memory
    memcpy (dst, src, len);             // Copy the block
    return dst;                         // Return the new string
}

8
Pax의 샘플 구현에서 알 수 있듯이 strdup (NULL)은 정의되어 있지 않으며 예측 가능한 방식으로 동작 할 것으로 예상되지 않습니다.
언 와인드

2
또한 malloc ()이 errno를 설정한다고 생각하므로 직접 설정하지 않아도됩니다. 내 생각에
Chris Lutz

5
@Alcot strdup은 문자열 복사본에 힙 메모리를 할당하려는 상황을위한 것입니다. 그렇지 않으면 스스로해야합니다. 이미 충분히 큰 버퍼 (malloc'ed 또는 기타)를 가지고 있다면을 사용하십시오 strcpy.
paxdiablo 2019

2
@acgtyrant : 표준에 의해 ISO 표준 (실제 C 표준)을 의미한다면, 그렇지 않습니다. 그것은 이다 POSIX 표준의 일부입니다. 그러나 ISO C의 공식적인 부분은 아니지만이를 제공하는 많은 C 구현 이 있지만, 그렇지 않은 경우에도이 답변의 5 개 라이너는 충분해야합니다.
paxdiablo

2
좋은 점, @chux, ISO { EDOM, EILSEQ, ERANGE }는 필요한 오류 코드 로만 요구됩니다 . 이에 대한 답변을 업데이트했습니다.
paxdiablo

86
char * strdup(const char * s)
{
  size_t len = 1+strlen(s);
  char *p = malloc(len);

  return p ? memcpy(p, s, len) : NULL;
}

아마 코드가 조금 더 빨리와보다 strcpy()는 AS \0문자가 (이미와 있었다 다시 검색 할 필요가 없습니다 strlen()).


감사. 내 개인 구현에서 나는 심지어 "더 나빠"도 만든다. 할당 실패 return memcpy(malloc(len), s, len);보다는 할당 충돌이 더 NULL낫습니다.
Patrick Schlüter

3
@tristopia 역 참조 NULL충돌하지 않는다; 정의되지 않았습니다. 충돌하는지 확인하려면 실패한 emalloc호출 abort을 작성하십시오 .
Dave

나는 알고 있지만 구현은 Solaris 또는 Linux에서만 (앱의 본질 상) 실행되도록 보장됩니다.
Patrick Schlüter

@tristopia : 최선의 방법으로 일하는 습관을 갖는 것이 좋습니다. emalloc다른 플랫폼에서 코드를 작성할 때 나중에 사용할 수 있도록 Solaris 또는 Linux에서 필요하지 않더라도 사용하는 습관을 가지십시오 .
ArtOfWarfare

51

다른 답변을 반복 strdup()해도 아무런 의미가 없지만 C 표준의 일부가 아니므로 C 관점에서 원하는 모든 것을 할 수 있습니다. 그러나 POSIX.1-2001에 의해 정의됩니다.


4
strdup()휴대용? POSIX 이외의 환경에서는 사용할 수 없습니다 (어쨌든 구현 가능). 그러나 POSIX 함수가 무엇이든 할 수 있다고 말하는 것은 상당히 비현실적입니다. POSIX는 C만큼 우수하고 더 대중적인 또 다른 표준 입니다.
PP

2
@BlueMoon POSIX를 준수하지 않는 C 구현은 여전히 strdup확장 기능을 제공 할 수 있다고 생각합니다 . 이러한 구현에서는 strdupPOSIX 함수와 동일한 방식으로 작동 한다고 보장 할 수 없습니다 . 이러한 구현에 대해서는 잘 모르지만 합법적 인 비 악성 구현은 char *strdup(char *)역사적인 이유로 제공 할 수 있으며에 대한 전달 시도를 거부 할 수 const char *있습니다.

C 표준과 POSIX의 차이점은 무엇입니까? C 표준에 따르면 C 표준 라이브러리에는 존재하지 않습니까?
Koray Tugay

@KorayTugay 그들은 다른 표준입니다. 특정 C 함수의 표준이 POSIX 표준을 준수하고 컴파일러 / 라이브러리가 해당 함수의 표준을 준수한다는 것을 알지 않는 한 관련되지 않은 것으로 처리하는 것이 좋습니다.
Matthew 읽기

17

에서 에서는 StrDup 사람 :

strdup()함수는로 가리키는 문자열의 복제 본인 새 문자열에 대한 포인터를 반환해야합니다 s1. 반환 된 포인터는에 전달 될 수 있습니다 free(). 새 문자열을 작성할 수 없으면 널 포인터가 리턴됩니다.


4

strdup ()은 종료 문자 '\ 0'을 포함하여 문자 배열에 대한 동적 메모리 할당을 수행하고 힙 메모리의 주소를 리턴합니다.

char *strdup (const char *s)
{
    char *p = malloc (strlen (s) + 1);   // allocate memory
    if (p != NULL)
        strcpy (p,s);                    // copy string
    return p;                            // return the memory
}

따라서 메모리를 할당하지 않고도 인수가 제공 한 문자열과 동일한 문자열을 제공합니다. 그러나 나중에도 여전히 해제해야합니다.


3

malloc 과 전달 된 문자열의 strcpy 를 실행하여 전달 된 문자열의 복제본을 작성합니다 . malloc의 버퍼는 호출자에게 리턴되므로 리턴 값 에서 자유롭게 실행해야 합니다.


3

strdupstrndupPOSIX 호환 시스템에서 다음 과 같이 정의됩니다.

char *strdup(const char *str);
char *strndup(const char *str, size_t len);

에서는 StrDup () 함수는 문자열의 사본을위한 충분한 메모리를 할당하고 str, 그것을 복사, 반환 포인터를 않습니다.

포인터는 이후 함수에 대한 인수로 사용될 수 있습니다 free.

사용 가능한 메모리가 충분하지 않으면를 NULL반환하고 errno로 설정하십시오 ENOMEM.

strndup () 대부분의 기능을 복사 len문자열의 문자는 str항상 복사 된 문자열을 종료 널 (null).


1

가장 중요한 것은 메모리 (위치 및 크기)를 직접 할당하지 않고도 첫 번째와 동일한 문자열을 제공하는 것입니다. 그러나 언급했듯이 여전히 해제해야하지만 수량 계산이 필요하지 않습니다.


1

진술 :

strcpy(ptr2, ptr1);

(이것이 포인터를 변경한다는 사실을 제외하고)와 같습니다.

while(*ptr2++ = *ptr1++);

이므로:

ptr2 = strdup(ptr1);

다음과 같습니다.

ptr2 = malloc(strlen(ptr1) + 1);
if (ptr2 != NULL) strcpy(ptr2, ptr1);

따라서 복사 한 문자열을 다른 함수에서 사용하려면 (힙 섹션에서 생성됨)을 사용할 수 있습니다 strdup. 그렇지 않으면 strcpy충분합니다.


0

strdup () 함수는 문자열 복제의 속기이며 매개 변수를 문자열 상수 또는 문자열 리터럴로 가져와 문자열에 충분한 공간을 할당하고 할당 된 공간에 해당 문자를 쓴 다음 할당 된 주소를 반환합니다. 호출 루틴을위한 공간.


1
의 인수 strdup는 문자열 상수 일 필요는 없으며 C 문자열이어야합니다 (예 :의 null 종료 배열) char.
chqrlie
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.