linux g++ strcpy overlap 현상을 겪어보신분 계신가요?

iknights의 이미지

안녕하세요.
개발 도중 c의 strcpy overlap 현상을 보고 혹시 저와 같은 현상을 겪어보신분이 있는지요?

문제는 동일 소스를 가지고 두개의 동일 환경에 g++ 컴파일 버전만 다른 시스템에서
테스트 결과가 상이 하여 이러한 증상을 겪어보신분이나 해결하신 분의 조언을 얻고자 합니다.

소스: test.cpp

#include <stdio.h>
#include <string.h>
 
int main(int argc, char** argv)
{
    char buf[10] = {0,};
    char* p = buf;
 
    sprintf(buf, " P01=1");
    p++;
 
    // strcpy overlap 현상
    strcpy(buf, p);
 
    fprintf(stderr, "%s\n", buf);
 
    return 0;
}
 
> g++ -o test test.cpp
> test

1. A 시스템 (x86_64-redhat-linux)
g++ version 4.1.2
결과: [P01=1]

2. B 시스템 (x86_64-redhat-linux)
g++ version 4.4.7
결과: [P0==1]

strcpy을 memcpy로 고쳐 overlap현상에 대해 정상 처리를 할수 있지만
문제는 이러한 곳이 프로젝트내 한 두군데가 아니다 보니 수정양이 상당할 것으로 보입니다.

이러한 현상을 혹 겪으신 분이나 해결하신분들에 대한 조언을 얻고자 합니다.
감사합니다.

cinsk의 이미지

strcpy()는 source와 destination이 overlap되면 안됩니다. (undefined behavior)

익명 사용자의 이미지

윗 분 말씀대로 저러한 코드 자체가 애초에 strcpy 에서 사용하면 안되는 겁니다.
그리고 현재 이런 문제가 발생하시는 원인은 gcc 버전도 있고, 64비트 타겟이기 때문입니다.

버전에 따라서 저런 문제가 정확히 언제 발생하는지는 확인을 안해봤습니다만 아마도
서로 상이한 버전의 glibc 를 참조하는 경우로 추측됩니다.

즉 플랫폼에 따라서 결과가 상이할 수 있고, 근본적으로 저런 문제가 발생하는 원인은
strcpy 가 단순히 1바이트씩 복사하는 코드가 아니라, xmm 명령으로 최적화되어 생성되기 때문입니다.
어떤 플랫폼에선 그냥 굉장히 단순한 1바이트 복사 코드이지만 어떤 타겟에선 xmm 최적화 코드가 있습니다.

정 코드를 수정하지 않고 꼭 해결해야 한다면 바이너리가 동적 컴파일 되어있다는 가정하에
참조하는 libc 를 슬쩍 변경해도 되지만 이건 사실 전혀 권장하고 싶지 않은 방법입니다.

klara의 이미지

memcpy도 안됩니다. 메모리 복사할 때 겹쳐도 되는건 memmove가 유일합니다.
하지만 memmove던 memcpy던 일일이 버퍼길이를 구해서 지정해줘야하니까 래퍼 함수를 새로 하나 만드셔서 다 고쳐야겠네요.
아니면 #define으로 strcpy를 래퍼함수로 재정의해주는 방법도 있고요.
어찌되었든 표준라이브러리 건드릴거 아니면 소스는 무조건 고쳐야죠.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.