Memory Copy

6 분 소요

POD

Trivial, Standard Layout, POD 에 대한 이해가 필수임.

  • 위 세가지의 공통된 특징은
    • 가상함수는 쓰면 안되고
    • 성질이 멤버변수도 적용되어야함
  • Trivial
    • 기본생성자(파라미터 없는거)와 대입연산자, 소멸자가 default 여야함.
  • Standard Layout
    • C 등의 다른 언어와의 Memory Layout 의 상호운용을 위한 것
    • 여러 Access Specifier에 걸쳐서 멤버변수를 두면 안되고, 멤버변수 각각도 마찬가지임.
      • Access 지정자에 따라 컴파일러마다 멤버변수의 메모리 할당이 다름 - 참고
      • 그러니 만약 있으면 Layout 이 컴파일러, 혹은 c/c++ 에서 달라질 수 있음
    • 상속에서 자식이든 부모든 멤버변수는 한쪽 클래스에만 있어야함.
      • 아니면 변수 Layout 이 컴파일러마다 달라질 수 있음
  • POD(Plain Old Data)
    • Trivial 이면서 Standard Layout 인것
    • C 와 완전히 상호작용이 가능한 구조체임.

Memcpy, Memmove

차이점

memmove() 는 메모리 겹침을 막을 수 있음.

  • dest ---- source ---- dest end ---- source end
  • 이런 경우는 -> 이 방향이면 source 가 복사중에 변경됨 - 참고
  • 이는 역방향으로 복사하면 해결됨
  • 그래서 처음 메모리 위치를 비교해서 복사할 방향을 결정함
  • 그런데 캐시 아키텍쳐 등에 따라 역방향이 느려질 수 있음 - 참고
  • memmove() 가 임시버퍼를 쓴다는 말은 구라임 - 참고

주의점

Non-Trivial Copiable 의 경우 문제 발생

관련 SO

std::shared_ptr<int> dst;
{
    std::shared_ptr<int> src = std::make_shared<int>();
    memcpy(&dst, &src, sizeof(src));
}
cout << dst.use_count() << endl;
-572662307

위처럼 POD 가 아닌 값은 대입 연산자에서 수행하는 동작을 못해서 오류가 있을 수 있음.


struct AAA
{
    virtual void Do() { cout << "AAA\n"; }
};

struct BBB : public AAA
{
    virtual void Do() { cout << "BBB\n"; }
};

int main()
{
    AAA src[1]; BBB dst[1];
    copy(src, src + 1, dst);
    ((BBB*)dst)->Do();
    memcpy(dst, src, sizeof(src));
    ((BBB*)dst)->Do();
}
BBB
AAA

위처럼 가상함수 포인터도 카피해서 문제가 생길 수도 있음.

std::copy

memmove() 처럼 메모리 겹침을 허용함.

Memcpy 와의 비교 SO

  • stdlib 에서 지원하므로 inline 최적화가 가능해서 std::copy 가 조금더 빠를 수 있다고 함.

Non-Trivial Copyable 한 자료형도 지원해줌

  • 이때는 일일이 Copy Assignment Operator 를 수행해서 조금 느릴 수 있음.
  • 아닌 경우는 memcopy() 나 그에 흡사한 동작을 수행한다고 함.

댓글남기기