memwatch 를 사용하여 프로그램이 죽는 원인을 파악하던중

MrLord의 이미지

memwatch 툴을 사용하여 메모리 누수 및 문제점을 찾고 있습니다.

프로그램은 다중쓰레드를 사용하는(약 50개) 프로그램입니다. memwatch에는 이러한 내용의 로그가 생성되는데요

relink: <477577> cta.h(370) attempting to repair MW-0x812a998...
relink: failed for MW-0x812a998; reverse chain fragmented at MW-0x812a038, 'prev' is 0x812a9f0
relink: <477577> cta.h(370) attempting emergency repairs...
relink: forward chain's last intact MW is MW-0x812aa38, 100 bytes at cta.h(362)
relink: forward chain's first damaged MW is MW-0x812a998, 100 bytes at cta.h(362)
relink: reverse chain's last intact MW is MW-0x811a360, 1200 bytes at cta.c(469)
relink: reverse chain's first damaged MW is MW-0x811a840, 1200 bytes at cta.c(469)
relink: emergency repairs successful, assessing damage...
relink: partial, 51 MW-blocks of 59036 bytes lost
internal: <477577> cta.h(370), mwIsOwned fails for MW-0x812a998
double-free: <477577> cta.h(370), 0x812a9bc was freed from cta.c(678)
relink: <943234> cta.c(678) attempting to repair MW-0x812aa90...
relink: MW-0x812aa90 not found in forward chain search
relink: MW-0x812aa90 not found in reverse chain search
relink: heap appears intact, MW-0x812aa90 probably garbage pointer
relink: partial, 52 MW-blocks of 59073 bytes lost
internal: <943234> cta.c(678), mwIsOwned fails for MW-0x812aa90
WILD free: <943234> cta.c(678), unknown pointer 0x812aab4
relink: <1047946> cta.c(678) attempting to repair MW-0x812aa38...
relink: MW-0x812aa38 is the head (first) allocation
relink: MW-0x812aa38 not found in reverse chain search
relink: heap verification FAILS - aborting program

어떻게 수정을 해야 할지 모르겠습니다. 더블프리가 나는 부분에선 아무리 따져봐도 더블프리가 일어 날수가 없는데

저런 로그가 생기구요 (잘못본건지.. 여러번 확인했습니다만) 혹 memwatch는 다중쓰레드에선 제대로 기능을 하지

못하는건 아닌가 하는 생각이 들기도 하고 머가 잘못된것인지 고수님들의 많은 조언 부탁드립니다.

그럼 오늘 하루도 행복한 하루되시길...

MrLord의 이미지

혹시 realloc이 문제의 소지가 있는것인가요? 로그에 나오는 relink라는 건 realloc을 일컽는건 아닌지 해서요

Anonymou의 이미지

소스상에서 free(ptr) 을

if (ptr) {
    free(ptr);
    ptr = NULL;
}

로 교체하세요. 매크로 함수로 만드는게 낫겠죠.

아니면 포인터 자체를 한번 더 싸서 alloc 하는 위치랑
free 하는 위치를 추적하시는게 빠를겁니다.

MrLord의 이미지

#define Free(x) if(x != NULL){free(x); x = NULL;}
를 사용하여 프리 합니다.

MrLord의 이미지

============= MEMWATCH 2.71 Copyright (C) 1992-1999 Johan Lindh =============

Started at Tue May 9 12:35:20 2006

Modes: __STDC__ 32-bit mwDWORD==(unsigned long)
mwROUNDALLOC==4 sizeof(mwData)==32 mwDataSize==32

relink: <46351> cta.c(678) attempting to repair MW-0x812a9f0...
relink: MW-0x812a9f0 not found in forward chain search
relink: heap verification FAILS - aborting program

ssehoony의 이미지

memwatch 를 사용해 보지 않아서 memwatch 가 버퍼오버플로우나 언더플로우까지 잡아 주는지는 모르겠네요
혹시 memwatch 가 버퍼오버플로우를 잡지 않는다면 버퍼오버플로우가 발생하지 않았는지 알아보세요
해당 alloc/free 부분에 아무리 봐도 이상이 없다면, 다른 코드에서 alloc 정보를 망가뜨릴수가 있는데요
alloc 정보를 망가뜨리는 대부분의 경우가 버퍼 오버/언더 플로우입니다.

MrLord의 이미지

감지 하여 로그에 남깁니다.. ㅎㅎ 사용해보지 않으신분들을 위해 잠시 소개 해드리면
http://www.linkdata.se/sourcecode.html 주소에서 다운받아서 사용하실수 있습니다 프리구요
더블프리, 언프리, 오버/언더 플로우, 등등.. 입니다.

Trace의 이미지

Free() 가 실행되는 도중에 racing condition이 발생할 수도 있지 않을까요? 그다지 확률이 높은 건 아니지만, thread가 50개씩이나 된다고 하면 가능할 것도 같습니다.

MrLord의 이미지

레이싱 컨디션도 생각을 해봤는데 Free()에들어가는 변수들(char *) 들은 모두 쓰레드의 지역변수들인데
발생할 소지가 있을까요? 혹시 Free()가 define 인것이 발생 소지가 있는건가요?
조금만더 자세히 말씀해주실수 있을지..... 아니면 malloc realloc free 함수들이 쓰레드 세이프하지
않은건 아닌지..(이건 아닐꺼라 생각하지만 너무 막막하다보니)
참고로 이런 테스트를 해봤습니다. memwatch로 로그도 찍으면서요 아래 코드를 잠시.. 보시면
int main(int argc, char **argv)
{
int i;
pthread_t p_thread;
for(i = 0; i 작으면 20; i++)
{
pthread_mutex_lock(&Async_Mutex);
pthread_create(&p_thread, NULL, thread_malloc, (void *)&i);
pthread_cond_wait(&Async_Cond, &Async_Mutex);
pthread_mutex_unlock(&Async_Mutex);
}
pause();
}
void *thread_malloc(void *data)
{
char *tmp = NULL;

pthread_mutex_lock(&Async_Mutex);
printf("Start Thread %d\n",*((int *)data));
pthread_cond_signal(&Async_Cond);
pthread_mutex_unlock(&Async_Mutex);

while(1)
{
//pthread_mutex_lock(&Malloc_Mutex);
tmp = (char *)malloc(1024);
//pthread_mutex_unlock(&Malloc_Mutex);
//Free(tmp);
if(tmp != NULL)
{
//pthread_mutex_lock(&Free_Mutex);
free(tmp);
//pthread_mutex_unlock(&Free_Mutex);
tmp = NULL;
}
}
}
이런것두 똑같은 에러로 죽더군요 중간에 주석처리된 부분 보시면 아시겠지만 뮤텍스를 이용해봐도
똑같은 에러로 죽네요.. 대체 문제가뭔지 감이 잡히질 않습니다.

ps : 소스넣을때 태그 어떻게 처리하나용 우.. 소스가 짤리네용

Trace의 이미지

사실 malloc()이나 free()의 thread-safe 여부는 사용하시는 컴파일러와 라이브러리에 달려 있습니다.
하지만 지금 실제로 사용되는 환경에서 malloc()이나 free()가 thread-safe하지 않다는 것은
좀 상상하기 어려울 것 같습니다.

Free()에 들어가는 변수들이 전부 local에서 할당되고 반환된다면 racing condition은 생각할 필요가
없습니다. 하지만 할당되는 위치가 global이거나 다른 thread에서 사용한다면 물론 문제가 될 수 있겠지요.

음, 이건 너무나 원칙적인 이야기입니다만, 소스코드가 없으니 이런저런 상상을 해 볼 수밖에요.

혹시 Free()에서 NULL을 할당해주는 것을 과신하신 부분이 있지 않을까 싶기도 합니다.
예컨대...

char * cp1 = (char *)malloc( sizeof(char) * 16 );
char * cp2 = cp1;
Free( cp2 );

코드가 이런 식으로 작성되어 있는 경우, Free()를 실행한 후 cp2는 NULL이겠지만
cp1은 원래 값 그대로일 겁니다. 여기서 cp1을 또다시 Free()하는 경우 double free가 되겠지요.
(역시나 상상일 뿐입니다만, 예를 들어서 그렇다는 겁니다.)

참고로, 바로 위에 올려주신 코드는 잘 안 보이는군요. ^_^

hwatk의 이미지

이미 오래전 글입니다만, 제가 확인한 내용을 써봅니다. 다음 definition을 선언해야 합니다.

memwatch.c

...
#define HAVE_PTHREAD_H 1 // 이 라인을 추가해서 사용하시면 됩니다.
...
#if defined(MW_PTHREADS) || defined(HAVE_PTHREAD_H)
#define MW_HAVE_MUTEX 1
#include
#endif

이를 사용하지 않으면, lock을 사용하지 않기에 memwatch가 사용하는 내부 구조체가 multi-thread환경에서 깨져버립니다.
그래서 abort가 발생하는 거구요.

그럼 비슷한 문제를 겪을 분들에게 도움이 됐으면 합니다.

댓글 달기

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