이 함수에 문제가 있나요?

lalupo20의 이미지

void GLObjectManager::drawView() {
	static int prevSize = 0;
	static int size = 0;
	list< GLObject* >::iterator obj_iterPos = objList.begin();
	list< GLObject* >::iterator obj_iterEnd = objList.end();
 
	for (; obj_iterPos != obj_iterEnd; obj_iterPos++) {
		size = objList.size();
		if (size != prevSize) {
			obj_iterPos = objList.begin();
			obj_iterEnd = objList.end();
			prevSize = size;
		}
		if (((GLObject*)(*obj_iterPos)) != NULL) ((GLObject*)(*obj_iterPos))->draw();
	}
}

리스트에는 1초안에 2~3개정도의 객체가 더해지고, 또 제거 됩니다.

이 함수 작동시키다보면 문제없이 잘 돌아갈때도 있고

중간에 에러가 발생하기도 하네요.

일단 문제는 draw()함수 호출하는 부분에서 문제가 발생하네요

(GLObject*)(*obj_iterPos) 이 부분이 널이 되거나 쓰레기값이 들어가면서 문제가 발생하는거 같은데

왜 이런 현상이 발생하는지 모르겠습니다.

조언 좀 부탁드리겠습니다.

세벌의 이미지

컴파일 할 때 Error 뿐 아니라 Warning 도 살펴보시면 도움이 될 겁니다.
gcc 라면

gcc -Wall 
로 해보셔요.
익명 사용자의 이미지

말씀하신 문제의 발생 원인하고는 별개일지도 모르겠습니다만, 주어진 코드는 멀티스레드 동작을 암시하는군요.
루프가 돌아가는 동안 다른 스레드가 objList에 뭔가 더 삽입하거나 삭제할 수도 있어서 이렇게 작성한 것이겠죠?

STL 컨테이너는 멀티스레딩의 data race에 안전하지 않습니다. 다른 스레드가 objList에 삽입/삭제를 하는 순간에 STL 컨테이너 자료구조가 잠시 일관성을 잃는 모습이 다른 스레드에 노출되거나, 어떤 스레드가 컨테이너의 요소를 사용하려는 순간 다른 스레드가 그것을 삭제해 버릴 수도 있지요.

설명이 너무 추상적이어서 이해를 못 하시겠다면 구체적인 예를 들어 드리죠. 주어진 코드가 if (size != prevSize) 테스트와 if (((GLObject*)(*obj_iterPos)) != NULL) 테스트를 통과한 뒤 draw 함수를 호출하기 직전에, 다른 스레드가 바로 그 객체를 objList에서 제거하고 삭제해 버릴 수도 있습니다. 그러면 draw 함수는 삭제된 객체에 대해 호출되겠죠.

이런 종류의 문제를 방지하기 위해서 적절한 메커니즘을 도입해야 합니다. 방법은 많습니다. mutex가 대표적이긴 하죠.

lalupo20의 이미지

좋은 댓글 감사드립니다.

shint의 이미지


http://codepad.org/PXetOWlC

#include <stdio.h>
#include <sstream>
#include <vector>
#include <list>
 
 
using namespace std;
 
list<int*> objList;
 
class CTest
{
public:
    CTest(){}
    ~CTest(){}
 
    void drawView();
};
 
class GLObject
{
public:
    GLObject(){}
    ~GLObject(){}
 
    void draw()
    {
        printf("-----------\n");
    }
};
 
void CTest::drawView() 
{
	static int prevSize = 0;
	static int size = 0;
	list< int* >::iterator obj_iterPos = objList.begin();
	list< int* >::iterator obj_iterEnd = objList.end();
 
	for (; obj_iterPos != obj_iterEnd; obj_iterPos++)
        {
		size = objList.size();
		if (size != prevSize) 
                {
                        printf("xxxx\n");
			obj_iterPos = objList.begin();
			obj_iterEnd = objList.end();
			prevSize = size;
		}
		if (((GLObject*)(*obj_iterPos)) != NULL) ((GLObject*)(*obj_iterPos))->draw();
	}
}
 
int main()
{
    GLObject * o1 = new GLObject();
    objList.push_back((int*)o1);
 
    GLObject * o2 = new GLObject();
    objList.push_back((int*)o2);
 
    GLObject * o3 = new GLObject();
    objList.push_back((int*)o3);
 
    CTest ct;
    ct.drawView();
 
    o3 = (GLObject *) objList.back();
    objList.pop_back();
 
    o2 = (GLObject *) objList.back();
    objList.pop_back();
 
    o1 = (GLObject *) objList.back();
    objList.pop_back();
 
    delete o3;
    delete o2;
    delete o1;
 
    return 0;
}
 
//
xxxx
-----------
-----------
-----------

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

lalupo20의 이미지

감사합니다.

댓글 달기

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