문제

사용하는 오래된 코드가 있습니다 qsort MFC를 정렬합니다 CArray 구조물이지만 가끔 충돌이 발생하고 있습니다 5월 여러 스레드가 호출됩니다 qsort 동시에. 내가 사용하는 코드는 다음과 같은 것 같습니다.

struct Foo
{
  CString str;
  time_t t;

  Foo(LPCTSTR lpsz, time_t ti) : str(lpsz), t(ti)
  {
  }
};

class Sorter()
{
public:
    static void DoSort();
    static int __cdecl SortProc(const void* elem1, const void* elem2);
};

...

void Sorter::DoSort()
{
  CArray<Foo*, Foo*> data;
  for (int i = 0; i < 100; i++)
  {
    Foo* foo = new Foo("some string", 12345678);
    data.Add(foo);
  }

  qsort(data.GetData(), data.GetCount(), sizeof(Foo*), SortProc);
  ...
}

int __cdecl SortProc(const void* elem1, const void* elem2)
{
  Foo* foo1 = (Foo*)elem1;
  Foo* foo2 = (Foo*)elem2;
  // 0xC0000005: Access violation reading location blah here
  return (int)(foo1->t - foo2->t);
}

...

Sorter::DoSort();

나는이 끔찍한 코드를 사용할 수있게하려고한다. std::sort 대신 위의 것이 실제로 안전하지 않은지 궁금하십니까?

편집하다: Sorter::DoSort 실제로 정적 함수이지만 정적 변수 자체를 사용하지 않습니다.

edit2 : SortProc 함수는 실제 코드와 일치하도록 변경되었습니다.

도움이 되었습니까?

해결책

당신의 문제가 반드시 Thread Saftey와 관련이있는 것은 아닙니다.

정렬 콜백 함수는 항목 자체가 아닌 각 항목에 대한 포인터를 사용합니다. 정렬하기 때문에 Foo* 실제로하고 싶은 것은 매개 변수에 액세스하는 것입니다. Foo**, 이와 같이:

int __cdecl SortProc(const void* elem1, const void* elem2)
{
  Foo* foo1 = *(Foo**)elem1;
  Foo* foo2 = *(Foo**)elem2;
  if(foo1->t < foo2->t) return -1;
  else if (foo1->t > foo2->t) return 1;
  else return 0;
}

다른 팁

SortProc은 올바른 결과를 반환하지 않으므로 데이터가 정렬 된 후에 데이터가 정렬되었다고 가정하여 메모리 손상으로 이어질 수 있습니다. QSORT가 분류하려고 할 때 QSORT를 부패로 이끌 수도 있지만 물론 구현에 따라 다릅니다.

QSORT의 비교 함수는 첫 번째 객체가 두 번째 객체보다 작고, 그렇지 않으면 긍정적 인 경우 ZERO보다 음수를 반환해야합니다. 현재 코드는 0 또는 1 만 반환하고 음수를 반환해야 할 때 1을 반환합니다.

int __cdecl Sorter::SortProc(const void* ap, const void* bp) {
  Foo const& a = *(Foo const*)ap;
  Foo const& b = *(Foo const*)bp;
  if (a.t == b.t) return 0;
  return (a.t < b.t) ? -1 : 1;
}

C ++는 실제로 스레드 안전에 대한 보장을하지 않습니다. 당신이 말할 수있는 가장 많은 것은 여러 독자 나 데이터 구조에 대한 단일 작가가 괜찮다는 것입니다. 독자와 작가의 모든 조합이 있으므로 어떻게 든 액세스 할 수 있습니다.

질문을 태그로 지정했기 때문에 MFC 태그 프로젝트 설정에서 멀티 스레드 런타임 라이브러리를 선택해야한다고 가정합니다.

DoSort-Method는 로컬 변수 만 사용하고 아무것도 반환하지 않기 때문에 현재 코드는 스레드 안전하지만 쓸모가 없습니다. 정렬중인 데이터가 분류기의 구성원 인 경우 여러 스레드에서 기능을 호출하는 것이 안전하지 않습니다. 게레날에서는 읽으십시오 재창조, 이것은 당신이 무엇을 찾아야하는지에 대한 아이디어를 줄 수 있습니다.

스레드를 안전하게 만드는 것은 객체가 스레드 안전한지 여부, 예를 들어 QSORT 스레드-안전을 만들려면 쓰기 또는 읽기 또는 객체에 대한 객체에 안전한 스레드를 안전하게 보장해야합니다.

PTHREADS MAN 페이지에는 스레드 안전이 필요하지 않은 표준 기능이 나와 있습니다. QSORT는 그들 중 하나가 아니므로 스레드-안전해야합니다. POSIX에서.

http://www.kernel.org/doc/man-pages/online/pages/man7/pthreads.7.html

그러나 Windows의 동등한 목록을 찾을 수는 없으므로 실제로 귀하의 질문에 대한 답이 아닙니다. 그것이 다르면 약간 놀랐습니다.

그러나이 맥락에서 "스레드-안전"이 무엇을 의미하는지 알아야합니다. 즉, 다른 배열에서 동시에 동일한 기능을 동시에 호출 할 수 있음을 의미합니다. QSORT를 통해 동일한 데이터에 대한 동시 액세스가 안전하다는 의미는 아닙니다 (그렇지 않음).

경고의 한마디로, 당신은 찾을 수 있습니다 std::sort 빠르지 않습니다 qsort. 당신이 그것을 찾으면 시도하십시오 std::stable_sort.

한 번은 Dobbs 박사에 Mark Nelson을 제시 한 코드를 기반으로 BWT 압축기를 썼고 수업으로 전환했을 때 그 규칙을 찾았습니다. sort 훨씬 느 렸습니다. stable_sort 속도 문제를 수정했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top