메모리에 대한 질문입니다.

maxnim의 이미지

안녕하세요?
궁금한게 있어서요...

요즘 메모리에 관련된 버그를 수정하는 일을 하고 있는데 이게 참 난감합니다.
이게 win32 만의 문제는 아니구요.. 일단 적어볼께요.

CRITICAL_SECTION g_cs;

EnterCriticalSection(&g_cs);

LeaveCriticalSection(&g_cs);

이런 형태의 코드인데요 하나의 자원에 대해 하나의 thread만 접근을 허용하는 겁니다.
그런데 어느 순간(원인모름) EnterCriticalSection()에 대해서 11bytes 만큼 뭔가
잘못되어서 제대로 처리를 못하고 프로그램이 죽어버리는 겁니다.

그래서 여기저기 조언을 구했는데...

/* 줄줄이 비엔나처럼 메모리 영역이 붙어있는 경우 */
char a[10];
char b[20];

프로그램 어디선가 b[0] 주소를 변경한다든지 어쩌다가 b[0]의 위치가 a[9]로 변경된다든지
이런 경우가 발생할 수 있다고 합니다.
만약 b[0]의 주소가 a[]의 영역을 침범하게 되면 a나 b나 둘 다 문제가 생길 수 있다고 하는데

#define S1 10
#define S2 20

/* 줄줄이 비엔나처럼 메모리 영역이 붙어있는 경우 */
char a[S1+4];
char b[S2+4];

memset(a, 0, sizeof(S1)); /* 요건 sizeof 땜시 샘플로... */
memset(b, 0, sizeof(S2));

이런 식으로 처리하는걸 권장한다고 하더라구요.
그래야 혹시나 저넘들이 문제가 생겨도 다른 메모리 영역을 침범할 확률이 적다고 합니다.
이렇게 말씀하신 분이 상당히 실력이 있는 분인데
개인적으로 정말 저런식으로 처리를 해야 안전한건지 모르겠습니다.

제가 쓴 코드는 생각하지 않으셔두 되는데요
배열, 혹은 메모리 크기를 정할때 저런식으로 해야 안전하다고 할 수 있는지요?

만약 그렇다고 한다면...
일단, default size를 정해놓고, 선언시에 쓸 size도 정해놓고 해버리면...
모든 코드를 저런 식으로 작성한다고 하면 앞으로 어떻게 될지 궁금합니다.

정말 저런 식으로 작업을 해야할까요?

superkkt의 이미지

뭐니뭐니해도 제일 좋은 방법은 메모리 침범이 발생하지 않도록 잘~ 하는거겠죠.. 근데 이게 현실적으로 불가능하고^^

동적할당의 경우에는 malloc/free의 wrapping function을 만들어서 메모리를 할당할때 요청한 사이즈에 앞/뒤로 추가 메모리를 할당해서 거기에 메직넘버를 기록하고, 해제할때 메직넘버를 검사하는 루틴을 사용하는 방법을 본적이 있습니다. 만약 메모리 해제시 앞/뒤의 매직넘버가 손상되었으면 오버/언더플로우가 발생한 경우로 간주해서 ASSERT 시킨도록하면 메모리 침범 문제를 해결하는데 도움이 많이 되겠죠.

위에 보여주신 방법도 좋은 방법인것 같습니다. 정적메모리의 사용이라서 제가 예로든 경우와 좀 다르긴하지만요.. 하지만 단지 완충영역을 통해서 문제가 발생했을때 프로그램이 사망하시지 않도록 도와준다점 외에는 큰 메리트가 없는것 같습니다. 그리고 메모리 침범이 발생하는 코드가 있다면 프로그램이 빨리 죽어주는것이 프로그래머 입장에서 더 좋을텐데요.. 위 코드는 버그를 더 찾기 어렵게 만드는것이 아닐까 싶네요^^

======================
BLOG : http://superkkt.com

======================
BLOG : http://superkkt.com

kewlbear의 이미지

습관적으로 memset으로 초기화(?)하는 사람들이 있는데 불필요한 경우가 많습니다. 잘 생각해보시고 꼭 필요한 경우에만 쓰는 것이 좋다고 생각합니다.
그런데 11바이트만큼이라는 건 어떻게 아셨는지 궁금하네요.

chadr의 이미지

우선 실력있으신분께서 말씀하신것은 어차피 메모리를 침범하는 버그의 경우에는 찾기도 힘들고
찾기위해서는 많은 노력이 필요하기 때문에 그냥 어느정도 갭을둬서 프로그램이 죽지 않도록 방어하시는것 같습니다.

하지만 제 생각으로는 별로 좋은 방법은 아닌것 같습니다. 우선 문제가 있는 코드를 저런식으로 방어를 해놓아봤자
결국에는 시한폭탄을 안고있는 코드입니다. 지금 당장은 문제가 없겠지만..
만약에 저런식으로 방어를 해놨다는걸 모르는 추후의 유지보수 프로그래머가 뭔가 기능추가를 했다고 생각해보면
분명 저런 코드 때문에 삽질을 하게 될건 불보듯 뻔합니다.

그리고 프로그램이 죽지는 않지.. 결과값이 정확히 나온다는 보장도 없습니다.
차라리 깔끔하게 죽어주고 코어덤프를 남겨주는 것이 프로그래머 입장에서도 버그를 찾기도 쉽습니다.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

cinsk의 이미지

제대로 프로그램을 만들었다면 멀쩡한 배열이 서로 영역이 겹치거나, 침범할 까닭이 없습니다. 프로그램을 잘못만들었기 때문이며, 조언하신 분이 알려준 코딩 스타일은 제가 보기에는 바람직한 코드가 아닙니다. 괜히 stack 영역만 더 잡아먹기 때문에, 근본적인 해결 방법이 아닙니다. 코드를 다시 한 번 분석해서 버그를 수정하기 바랍니다. valgrind(1)와 같은 툴이 도움이 될 수도 있습니다.

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

댓글 달기

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