qt(C++) 에서 메모리 할당(malloc)후에 해제(free) 할때 세그멘테이션 에러가 나는데 왜 이러는지 모르겠네요

biokk의 이미지

생성자에서 메모리를 할당하구요
소멸자에서 메모리 해제하는 코드를 넣어놨느데요

생성자
test = (unsigned char*)malloc(512);

소멸자
if(test != NULL)
{
free(test)<---------------여기서 세그멘테이션
test= NULL;
}

이런식으로 처리하는데요

항상 free하는 부분에서 세그멘테이션 에러가 나더라구요
생성자에서 디버깅해서 메모리 할당하는것 확인까지 했는데도 이런 에러가 나는데요

다른 곳에서 메모리 해제 하는 데도 없는데 저러니깐 원인을 모르겠습니다.
프로그램 상에서 동적 메모리 할당(malloc)을 여러개 하는데 저 한곳에서만 저런 에러가 나는데요
메모리 할당을 많이 해서 그런가...원인이 무엇인지 모르겠네요
항상 세그멘테이션이 나는게 아니고..어떨때는 잘되고 어떨때는 에러가 나더라구요
감사합니다.

익명 사용자의 이미지

이미 해제된 메모리를 다시 해제한다고 해서 세그먼테이션 오류가 나지는 않습니다.
물론 경우에 따라서 Double free bug 등의 취약점은 있을 수 있겠으나
당장 문제가 되는 부분은 아닙니다.

힙 해제시에 발생하는 세그먼테이션 오류는 보통 할당한 크기 이상으로
데이터를 쓰셨을 때 발생합니다. 가령 512바이트 할당했는데 1024바이트를 쓴다던가 하는 경우입니다.
malloc 과 같은 함수는 기본적으로 Double Linked List 등으로 내부적인 메모리 관리를 하기 때문에
힙과 힙 사이에는 항상 이런 부가적인 데이터가 들어 있으며, 할당된 크기 이상으로 쓰게 되면
Heap Corruption 이 발생할 수 밖에 없습니다.

또한, 그렇다고 30바이트 할당했는데 31바이트 쓴다고 해서 당장 에러가 나거나 하진 않습니다.
Visual Studio 의 Debug 모드 처럼 따로 힙 오버플로우가 발생했는지 체크해서 1바이트만 넘어도
오류 메시지를 표시해주는 경우가 아니면 그냥 Release 로 아무런 디버깅용 코드가 없는 경우
단지 할당된 공간 이상으로 쓴다고 해서 문제가 발생하지는 않습니다.

이는 또한 malloc 과 같은 함수들이 내부적으로 특정 크기의 배수로만 할당을 한다는 이유도 작용합니다.
페이징 때문에 이런 식으로 처리하며 따라서 실제로 쓰기 가능한 영역은 조금 더 많을 수 있습니다.

어쨌든 결론은 메모리를 쓰는 부분에서 오버플로우가 되지 않나 살펴보시기 바랍니다.

dltkddyd의 이미지

test에 메모리를 할당하지 않았더라도 생성자에서 빈 test에 NULL을 채우지 않았을 경우(종종 쓰레깃값이 채워지기도 하는데)메모리를 할당한 경우로 알고 알고리즘을 구현하셨다면 그것 때문에 free에서 에러가 발생했을 수 있습니다. 즉 할당하지도 않는 다른 곳의 메모리를 깨려하는 경우가 있을 수도 있는데, 혹시 그 경우가 아닐까요?

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

익명 사용자의 이미지

복사생성자같은 경로를 통해서 이중해제가 이뤄졌을거라 추측되는군요

라스코니의 이미지

이런 생각도 드는군요.
할당된 메모리가 프로그램의 실행 큐에서 사용되고 있엇고 free()할 때도 계속 사용되니까 segmentation fault가 나는 거라구요.

mirheekl의 이미지

일단 저도 맨 윗분 말씀대로 할당받은 영역 이상의 메모리를 사용했다에 한표입니다. 메모리를 사용하는 구간에서 바운더리를 초과했는지를 검사하는 코드를 넣어보시면 좋겠군요. (이걸 감시하는 툴들도 있습니다만 일단 생략하겠습니다.)

그리고 위에 나온 코드도 (비록 세그멘테이션 폴트와는 무관할 수 있지만) 멀티스레딩 환경에선 쓰기 어려워 보입니다. 혹시 멀티스레딩 환경이면 참고해보세요.

if(test != NULL)
{
    free(test);        -(1)
    test= NULL;        -(2)
}

(1)번이 수행된 직후 (2)번이 수행되기 직전 다른 스레드에서 저 test 값을 참조할 수 있게 됩니다. (변수 자체는 프라이빗이라 해도 외부 메서드 등에 의해 참조될 수 있겠죠.) 따라서 여기서 추가적인 동기화를 해줘야 합니다.

프로그램 구조에 따라서 다음과 같이 바꾸는 것만으로 해결될 수도 있습니다만, 보통은 제대로 된 동기화를 해줘야 합니다.

    temp = test; 
    test = null; 
    free(temp);

이렇게 바꿔주면 워커 스레드에서 포인터를 체크해줄 경우 test를 사용하는 새 작업은 시작되지 않겠지만, 기존에 돌아가던 작업이 있었을 경우에는 여전히 문제가 발생하겠죠. 결국 완벽하게 해결하려면 동기화(또는 기타 비슷한 처리)를 해줘야 합니다.

그리고 또 한가지 아주 사소한 팁을 드리면.. free(0)은 에러를 발생하지 않습니다. 따라서 if문은 꼭 넣지는 않아도 됩니다.

--

댓글 달기

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