2017-03-09 1 views
1

그래서 1-99 사이의 임의의 값을 갖는 2-d 어레이 [5] [12]를 생성하는 할당이 있습니다. 그런 다음 pthreads를 사용하여 배열의 각 요소에 1을 더하거나 1을 뺀 다음 결과를 출력하고 2, 3 또는 4 스레드로 프로세스를 나눕니다. 스레드의 수는 사용자가 명령 행에서 입력 한 내용에 따라 다릅니다. 컴파일하고 실행하는 코드가 있습니다. 그러나 원하는 출력은 숫자 3을 입력 할 때만 인쇄됩니다. 내가 코드에서 어디서 잘못되었는지 말해 줄 수 있니? 나는 처음에는 pthreads를 이해하는 데 어려움을 겪고 있습니다. 두 번째 루프에서 return 문을 제거하면 생성 된 스레드의 수가 2 인 경우pthread를 사용하여 2-d 어레이를 인쇄하십시오.

#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <ctype.h> 
#include <pthread.h> 
#include <iostream> 

using namespace std; 
int list[5][12]; 
int rows = 5; 
int cols = 12; 
int threadc; 

void *threadf(void *arg) 
{ 
    int x = (int) arg; 
    for(int i = (x*60)/threadc; i < ((x+1) * 60)/threadc; i++) 
    { 
     for(int j = 0; j < 12; j++) 
     { 
      if (list[i][j] % 2 == 0) 
       list[i][j] += 1; 
      else 
       list[i][j] -= 1; 
     } 
    } 
} 

void cArray() 
{ 
    srand(time(NULL)); 
    for(int i = 0; i < 5; i++) 
    { 
     for(int j = 0; j < 12; j++) 
     { 
      list[i][j] = rand() % 99 + 1; 
     } 
    } 

} 

void pArray(int list[][12], int rows, int cols) 
{ 
    cout << "\n"; 
    for(int i = 0; i < rows; i++) 
    { 
     for(int j = 0; j < cols; j++) 
     { 
      cout << list[i][j] << " "; 
     } 
     cout << "\n"; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    if(argc != 2) exit(0); 
    threadc = atoi(argv[1]); 
    assert(threadc >= 2 && threadc <=4); 
    pthread_t *thread; 
    thread = new pthread_t [threadc]; 
    if(thread == NULL) 
     exit(0); 
    cArray(); 
    cout << "2-d Array: "; 
    pArray(list, rows, cols); 
    int t; 
    for(int i = 0; i < threadc; i++) 
    { 
     t = pthread_create(&thread[i], NULL, threadf, (void *)i); 
     if (t != 0) 
      return 1; 
    } 
    for(int i = 0; i < threadc; i++) 
    { 
     t = pthread_join(thread[i], NULL); 
     if(t != 0) 
      return 1; 
    } 
    cout << "Modified 2-d Array: "; 
    pArray(list, rows, cols); 
    return 0; 
} 
+0

숙제가 있습니까? – hmatar

+0

예. 여기서 허용되지 않습니까? –

+0

당신이 당신의 일을 보여주고있는 것처럼 보이고 지금까지 그것은 가능합니다. 그래도 몇 가지 변경 사항을 권장합니다. "내 원하는 출력"표시하십시오. 또한 무엇을 얻고 있는지 보여줍니다. 권장 사항 : 무작위 숫자없이 시작하여 스레딩이 분류 될 때까지 동일한 숫자를 반복해서 테스트 할 수 있습니다. 개선 또는 오류를 쉽게 발견 할 수 있습니다. – user4581301

답변

-1

은 어떻게 든 thread_join는 프로그램이 최종 출력을 인쇄, (내 경우 22) 오류 코드를 반환합니다. 이 링크에 따르면

for(int i = 0; i < threadc; i++) 
{ 
    t = pthread_join(thread[i], NULL); 
    if (t != 0) 
     return 1; // <- your program works if you comment out this. 


} 

: http://minirighi.sourceforge.net/html/errno_8h.html 22 '은 나사 결합 가능한 해제는'의미 EINVAL이다.

pthread_join의 반환 값에 신경을 써서 thredf 끝에 성공적으로 종료 함수 (pthread_exit(NULL);)를 추가하는 것이 좋습니다. 또한 @ user4581301에 언급 된 버퍼 오버런을 피하기 위해 데이터에 대한 포인터를 전달할 수 있습니다.

int main(int argc, char *argv[]) 
{ 
    if(argc != 2) exit(0); 
    threadc = atoi(argv[1]); 
    assert(threadc >= 2 && threadc <=4); 
    pthread_t *thread; 
    thread = new pthread_t [threadc]; 
    int *data = new int[threadc]; // <- NOTICE HERE! 

    if(thread == NULL) 
     exit(0); 
    cArray(); 
    cout << "2-d Array: "; 
    pArray(list, rows, cols); 
    int t; 
    for(int i = 0; i < threadc; i++) 
    { 
     data[i] = i; 
     //            NOTICE HERE! 
     t = pthread_create(&thread[i], NULL, threadf, (void *)(&data[i])); 
     if (t != 0) 
      return 1; 
    } 
    // ... 
+0

일종. 우연히 작동합니다. 0x03은 ​​그러한 스레드가 없다는 것을 의미하므로 다른 오류를 마스킹하는 것입니다. 알아 내고 싶은 것은 두 번째 스레드가없는 이유입니다. – user4581301

+0

@user 당신의 솔루션을 위해서 당신은 thread_join이 리턴하는 것을 신경 쓸 필요가 없습니다. 반환 된 오류가 유용 할 수있는 몇 가지 조건이 있기 때문에 스레드가 교착 상태 또는 EINVAL입니다. POSIX 튜토리얼을 면밀히 살펴 본다면 대부분의 예제는이 함수가 반환하는 것을 보지 않습니다. 부모 스레드가이 함수를 호출하는 가장 기본적인 작업은 모든 자식 스레드가 종료 될 때까지 차단하는 것입니다. 필자는 수년 동안 멀티 스레드 프로그램을 작성해 왔으며이 함수가 반환하는 것을 신경 쓰지 않았습니다. 중요한 행동입니다. – hmatar

+0

내 해결책이 아닙니다. 친구. 진짜 문제는'threadf'에서 버퍼 오버런입니다. 여러분의 대답은 그것을 숨기고 있습니다. – user4581301

0

은 X = 0 threadf에 루프 외부에서 살펴 수 있습니다 및 threadc = 4

for(int i = (0*60)/4; i < ((0+1) * 60)/4; i++) 
    for(int i = 0; i < (1 * 60)/4; i++) 
    for(int i = 0; i < 60/4; i++) 
    for(int i = 0; i < 15; i++) 
:

그래서 thredf

void *threadf(void *arg) 
{ 
    cout << endl; 
    int x = *((int*)arg); // <- NOTICE HERE! 
    for(int i = (x*60)/threadc; i < ((x+1) * 60)/threadc; i++) 
     //... 
    } 
    pthread_exit(NULL); // <- NOTICE HERE! 
} 

그리고 주요 같은 것

i 범위는 0에서 14까지입니다. i는 다음과 같이 사용됩니다. list[i][j]이므로 list[14][11]에 대한 정보는 어디로 갈지 고려하십시오. 잘 정의 된 범위 바깥 쪽 int list[5][12]; 나쁜 smurf가 발생합니다. 정의되지 않은 동작이므로 기술적으로 아무도 어떤 일이 발생하는지 알지 못합니다. 우리는 꽤 좋은 추측을 할 수 있습니다.

int list[5][12]; 
int rows = 5; // probably overwritten by write to list[6][0] 
int cols = 12; // probably overwritten by write to list[6][1] 
int threadc; // probably overwritten by write to list[6][3] 

그래서 rowcolumn는 이동하지만 아무도 관심이 없다. 코드는 절대 사용하지 않습니다. 하지만 threadc ... 그 곳 곳곳에 사용됩니다. 사실 루프 종료 조건에서 사용됩니다. 더 나쁜 것이 여기에서 생길 것 같다. 또한 작성되어 결합되는 스레드 수를 판별합니다. 일부 스레드는 작성되지 않을 수 있습니다. 프로그램이 존재하는 것보다 많은 스레드에 참여하려고 시도 할 수 있습니다.

어쨌든, 정의되지 않은 동작. 나는 컴파일러가 전술 핵무기 공격을 명령 한 코드를 생성하지 않았다는 것에 모두 기뻐해야한다고 생각한다. 이것은 숙제 문제이므로 수학 OP를 통해 풀이 할 필요는 없습니다. for 루프를 사용하면 여러 스레드에서 작업을 올바르게 나눌 수 있지만 배열을 크기가 5 * 12 인 1D 배열로 간주 할 것을 제안합니다. 하나의 for 루프에서 1D -> 2D 색인 생성을 수행하는 것입니다.

기타 사항 :

main에서 i에 대한 사용 uintptr_t 대신 intthreadfx.uintptr_tvoid *으로 변환됩니다.

루프 카운터 및 배열 인덱서에는 size_t과 같은 부호없는 변수를 사용하십시오. 그들은 uintptr_t과 잘 어울리며 부정적인 배열 인덱스는 절대로 원하지 않습니다.

포인터 대신 std::vector을 사용하고 스레드 목록을 사용하려면 new을 사용하십시오. new과 포인터를 사용해야하는 경우 완료 한 후에는 목록을 삭제해야합니다.

pthread 대신 std::thread을 사용할 수 있는지 확인하십시오.

return에서 threadf을 추가하십시오.

관련 문제