strcpy의 dest, src 버퍼 중복(overlap)시 오작동 어떻게 생각하십니까?

lmh8502의 이미지

SYNOPSIS
#include

char *strcpy(char *dest, const char *src);

strcpy 시 같은 버퍼 즉 다음과 같이

char buf[32]="abcdefg1234";
strcpy(buf, buf+3);

이럴경우 buf의 값은 "defg1234" 가 되는게 맞습니다

하지만 몇몇 컴파일러 혹은 libc 에서 버퍼가 overlap 되서 문자(char)가 중복되는 경우가 발생합니다

그래서

while( *dst++ = *src++ );

식으로 strcpy 함수를 만들어서 사용하는데요.

이것의 근본적인 원인이 뭔지 공유를 하고 싶네요

귀찮아서 strcpy에 같은 버퍼, 포인터 연산까지 하는데 몇몇 OS에서 저런 오작동을 일으키니

결과가 달라지는 참혹한 현상이 발생합니다..

mirheekl의 이미지

strcpy 설명서를 보면 해당 작업을 지원하지 않는다고 분명히 언급하고 있으므로 사실 오작동은 아니지요.
이런 일이 일어나는 이유는 오버랩이 일어날 수 있다고 가정하고 함수를 구현할 경우 최적화할 수 있는 여지가 줄기 때문입니다.

예를 들어, 메모리를 거꾸로 읽으면 퍼포먼스가 좋은 시스템이 있다 가정해봅시다. 그럼 본문의 예에서는 널 캐릭터가 먼저 복사될것입니다. 그럼 그 복사된 널 캐릭터가 소스 스트링을 파괴하겠죠. 똑같은 얘기로, 본문의 예를 보시면 buf를 buf+3에 복사하는 건 파괴된 소스가 참조될 가능성이 있므으로 쓰면 안된다고 이미 인식을 하고 계시죠? 제가 언급한 예에선 오히려 이 방식은 (메모리만 제대로 할당돼있다면) 정상 동작합니다. 결국 버퍼 오버래핑시 답이 꼭 어떻게 나와야 한다.. 라는 건 구현 방법을 명시하지 않는 한 불가능한 셈입니다.

매뉴얼에 내부 구현사항 및 제약조건을 정확하게 명시하는 방법도 있지만, 이런 방법은 이식성을 심각하게 해치겠지요. 그래서 그냥 오버래핑을 지원하지 않는다고 명시하고 플랫폼별로 각자 최적화를 하는 방법이 최선이었을 거라고 생각하고 있습니다.

반면 memmove등 몇몇 함수의 경우는 오버랩 상황도 명시적으로 지원을 하고 있고요, 그래서 퍼포먼스가 그만큼 떨어집니다. 이부분 상관없다면 그런 함수를 항상 쓰시는 것도 방법이겠네요. (현재 하고 계신 것이 바로 그것.)

어떤 분이 퍼포먼스 테스트를 해놓은 자료가 있어서 올려봅니다.
http://www.velocityreviews.com/forums/t314980-comparative-performance-str-functions-vs-mem-functions.html

속도와 오버런을 둘 다 놓치기 싫다면 사용자 함수를 하나 작성해서 버퍼가 겹칠 가능성이 있는지 확인하고 이후에 적당한 펑션을 호출해주면 되겠습니다.

--

klara의 이미지

하지말라는걸 하고서 그걸 오작동이라고 하면 안되죠. 그냥 프로그램을 잘못짜신겁니다.

익명 사용자의 이미지

overlap에도 동작하고 싶으면 memmove를 쓰면 됩니다

qiiiiiiiip의 이미지

char buf[32]="abcdefg1234";
strcpy(buf+3, buf);

이후에 buf는 어떻게 되어야하는지요?
while( *dst++ = *src++ );

로 strcpy(buf+3,buf)를 돌리면 어떻게 될까요?
아마 더 참혹한 결과가 나겠지요.

cpy 개념 자체가 overlap이 있는 경우에 모호합니다.
overlap이 있는 경우 memmove가 맞는 방법입니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.