malloc시 debugging

achrom의 이미지

malloc을 하다가, 프로그램이 죽습니다.

Quote:

...
printf("1");
ptr = malloc(1000);
printf("2");
...

대략 상황은 이런데, 1은 찍히고, 2는 안찍힙니다.
malloc 자체의 문제일까요?
아니면, 그 이전에 무언가 잘못했을까요?
이런 경우에 어떻게 debugging하십니까?
버려진의 이미지

ptr이 초기화가 안됐거나 중간에 엉뚱하게 바꼈을 거라고 봅니다.

achrom의 이미지

ptr을 참조하다가 죽는 것이 아니라, malloc을 하다가 죽는 것입니다.
참 이상합니다.

익명 사용자의 이미지

bluebayou wrote:
malloc을 하다가, 프로그램이 죽습니다.
이런 경우에 어떻게 debugging하십니까?

gcc 에서 -g 옵션주고 컴파일 하시고
ulimit 로 core file size 확인하신후 (적절히 바꾸고)
프로그램 실행시키고 죽으면 core가 생성될겁니다.
gdb 를 이용해서 확인해보세요

andysheep의 이미지

bluebayou wrote:
malloc을 하다가, 프로그램이 죽습니다.
Quote:

...
printf("1");
ptr = malloc(1000);
printf("2");
...

대략 상황은 이런데, 1은 찍히고, 2는 안찍힙니다.
malloc 자체의 문제일까요?
아니면, 그 이전에 무언가 잘못했을까요?
이런 경우에 어떻게 debugging하십니까?

malloc 사용할 때 메모리 받는 포인터 변수의 데이타 형을 지정해 줍니다.

위에서 ptr 이 struct my_type 이라고 가정하면
ptr = (struct my_type *) malloc ( 1000 * sizeof (struct my_type) )

if ( ptr == NULL )
printf("Out of memory");

malloc에서 메모리 할당 실패하면 NULL 포인터 넘기고, 프로그램에서
NULL 포인터 변수 참조하면 실행 도중 이 참조부분에서 프로그램 멈춥니다.

C나 C++에서 메모리 버그 디버깅은 gdb 강추합니다.
-g 옵션 주고 gdb에서 실행파일 돌리면 위와 같은 경우 버그 있는 소스 코드의 위치를 gdb가 가르켜 주고, 포인터 변수의 내용도 알 수 있습니다.
NULL 값 가지는 포인터 변수는 위 예를 들면 disp ptr로 실제 ptr 변수 주소나 내용을 볼 수 있습니다.

Devuan 1.0 (Debian without systemd)
amd64 station: AMD FX(tm)-6100 Six-Core Processor, 8 GB memory, 1 TB HDD
amd64 laptop: HP Touchsmart

글쇠판: 세벌 최종식, 콜맥 (Colemak)

liongo의 이미지

Quote:
...
printf("1");
ptr = malloc(1000);
printf("2");
...

저코드만 봐선 멜록에서 죽었다고 확신할수 없습니다..

올리신 내용을 보셔도 2번이 찍히지 않는다고 해서 malloc에서

죽었다고 확신을 가지시면 안되지요.. :)

보시면 아시겠지만 "1", "2"로 찍으시면 터미널에 문자가 버퍼링 된상태에

서 죽을경우 2가 안찍힐수있는 상황이 옵니다.. 제일 정확한것은 물론

gdb로 확인하시는것입니다.. 2가 안찍힌다고 malloc부분이 문제라고

생각하시는것은 차후에 심각한 삽질로번질수 있습니다..

' 형식이 내용을 규정한다. '

liongo의 이미지

#include <stdio.h>

int main()
{
        char *test = NULL;

        printf("1");
        printf("2");
        strncpy( NULL, test, 128 );

        return 1;
}

덧붙여봅니다.. 기분이 꿀꿀해서..

이부분도 해보시면 알겠지만 strncpy에서 죽지만 1,2 모두 찍히지 않고 죽습니다..

참고하시길...

' 형식이 내용을 규정한다. '

achrom의 이미지

답변 감사드립니다.
약간의 오해가 있는 것 같아서, 질문을 조금 수정하고자 합니다.

Quote:
...
void *ptr;
printf("1\n");
ptr = malloc(1000);
printf("2\n");
if (!ptr) {
printf("Not enough memory!!\n");
exit(1);
}
...

위에서 2가 안찍힙니다.
Visual C++을 사용하고 있습니다.
gcc로 수정해서 테스트해보고 싶지만, Win32 API를 많이 사용하는 큰 프로그램이라서, 어렵네요 -.-
더 이상한 점은 debug 모드로 컴파일 하면 괜찮은데,
release 모드로 컴파일해서 실행하면 죽는다는 것입니다.
그래서, debugger로 따라가지 못하고, printf로만 살펴보았습니다.
혹시, 좋은 디버깅 방법이나 제가 잘 모르고 있는 부분이 있을까요?
thisnome의 이미지

bluebayou wrote:
답변 감사드립니다.
약간의 오해가 있는 것 같아서, 질문을 조금 수정하고자 합니다.
Quote:
...
void *ptr;
printf("1\n");
ptr = malloc(1000);
printf("2\n");
if (!ptr) {
printf("Not enough memory!!\n");
exit(1);
}
...

위에서 2가 안찍힙니다.
Visual C++을 사용하고 있습니다.
gcc로 수정해서 테스트해보고 싶지만, Win32 API를 많이 사용하는 큰 프로그램이라서, 어렵네요 -.-
더 이상한 점은 debug 모드로 컴파일 하면 괜찮은데,
release 모드로 컴파일해서 실행하면 죽는다는 것입니다.
그래서, debugger로 따라가지 못하고, printf로만 살펴보았습니다.
혹시, 좋은 디버깅 방법이나 제가 잘 모르고 있는 부분이 있을까요?

printf("1\n"); 이전 라인에 다음 코드를 추가해보세요.

setbuf(stdout, 0);

결과가 어찌 나올지.. :)

익명 사용자의 이미지

... 
void *ptr = NULL; 
printf("1\n"); 
ptr = (void*)malloc(1000); 
printf("2\n"); 
if (!ptr) { 
printf("Not enough memory!!\n"); 
exit(1); 
} 
... 

로해보시길.. debug->release 안되면 황당하죠 쩝..

저도 윈도는 문외한인지라.. 변수 초기화에 따라 예외동작을

간혹? 하는듯합니다. 그리고 보통 오버플로우가 나느것이..

디버그에서는 동작하다가 릴리즈에서는 죽는경우가 많았던것같습니다..

바운스체커로 한번 체크해보시는것도 괜찬읗것 같습니다..

단순 싱글쓰레드로 저코드부분만 지나간다고 했을때의 문제인것같진 않네요..

M.W.Park의 이미지

debug mode에선 free를 해도 free가 그 순간에 일어나지 않고 free되었다는 것만 mark해놓습니다.
(즉, free 후 malloc request가 있을 경우 debug mode에선 직전에 free한 영역을 이용하지는 않습니다. release mode는 allocation 정책에 따라 크기가 적당하면 직전에 free한 영역을 이용할 수 있지만요. 이런 식으로 해놓아야 debug mode에서 포인터가 가리키는 곳의 내용을 추적할 수 있죠.)

제가 보기엔 모종의 리소스가 malloc/free pair를 이루지 못한 상황으로 보입니다.

제 3의 장소에 malloc/free 들을 살펴보시기바랍니다 (특히 문제의 코드 바로 직전의 메모리 관련 코드들).
(create/release 계열의 api도 포함해서...8))

-----
오늘 의 취미는 끝없는, 끝없는 인내다. 1973 法頂

achrom의 이미지

도무지 원인을 알 수 없어서, 문제가 되는 부분만 잘 추려서, VC++과 gcc로 컴파일해봤습니다.
VC++에서는 여전히 문제가 발생하는데, gcc에서는 문제가 없습니다.
이런 경우에는 어떻게 생각해야 할까요?
VC++에 문제가 있다고 생각할 수 있는 걸까요?

saxboy의 이미지

malloc()에서 세그폴트를 받았다면, 그리고 환경에 따라 제대로 작동하기도 하고 아니기도 하다면, 다른 부분을 잘못 작성하셨을 가능성이 99.9999%입니다. 전혀 관계가 없어보이는 곳에서 메모리를 잘못 다루었기 때문에 다음에 호출되는 malloc()에서 에러가 생기는 것입니다.

애꿎은 시스템 라이브러리 탓하는 분도 여럿 보았습니다만, 그보다 먼저 다른 부분에서 포인터를 잘못 사용한 곳이 없는지 확인해보시는 것이 순서일것 같습니다. 에러가 생긴 부분이 호출되기 바로 직전에 호출되는 malloc/free/new/delete등등을 사용하는 함수 부분을 검사해보세요.

조금 어려운 코딩을 하시려면 넘어야 하는 문제이거니 생각하세요. "malloc에서 에러가 생겨요"는 C프로그래밍의 FAQ중 하나라고 생각하셔도 좋습니다.

혹시 10바이트짜리 버퍼에 11바이트를 쓰는 것과 비슷한 로직이 있는 곳이 없는지 strcpy()나 비슷한 콜을 중심으로 먼저 살펴보세요. 바운드체커로 한번 검사해보시면 웬만한 경우에는 잘못된 부분을 바로 찾을 수 있습니다.

익명 사용자의 이미지

그냥 속편하게 purify쓰세요. -_-;
double free, freed memory access(read/write), memory leak, memory out of bounds access(read/write) 등등을 check해 줍니다.

achrom의 이미지

정말 정말 감사합니다.
말씀하신 tool을 사용해서 문제를 찾았습니다.
죽는 malloc 이전에, 이미 문제가 발생되어 있었습니다.
이전에 할당된 영역의 바깥을 참조했기 때문이었습니다.
다시 한번 감사드립니다.

댓글 달기

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