2010-05-11 5 views
1

구조체를 대기열에 추가 한 후 다음 코드로 분할 오류가 발생합니다.C의 대기열을 사용하는 분할 오류

세그먼트 오류는 MAX_QUEUE가 높게 설정되었을 때 발생하지만 100 (또는 200)을 낮게 설정하면 오류가 발생하지 않습니다. 마지막으로 C로 프로그래밍 한 이후로 어느 정도 도움이되었습니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define MAX_QUEUE 1000 

struct myInfo { 
     char data[20]; 
}; 

struct myInfo* queue; 
void push(struct myInfo); 
int queue_head = 0; 
int queue_size = 0; 

int main(int argc, char *argv[]) 
{ 
     queue = (struct myInfo*) malloc(sizeof(struct myInfo) * MAX_QUEUE); 

     struct myInfo info; 
     char buf[10]; 
     strcpy(buf, "hello"); 

     while (1) 
     { 
       strcpy(info.data, buf); 
       push(info); 
     } 
} 

void push(struct myInfo info) { 
     int next_index = sizeof(struct myInfo) * ((queue_size + queue_head) % MAX_QUEUE); 
     printf("Pushing %s to %d\n", info.data, next_index); 
     *(queue + (next_index)) = info; 
     queue_size++; 
} 

출력 :

Pushing hello to 0 
Pushing hello to 20 
... 
Pushing hello to 7540 
Pushing hello to 7560 
Pushing hello to 7580 
Segmentation fault 
+0

을 'struct myInfo queue [MAXQUEUE]'로 선언하고'queue [next_index]'와 같은 표현식으로 요소를 참조하는 것이 현명 할 수도 있습니다. C에서 잠시 동안 프로그래밍하지는 않았지만. –

답변

4

나는 당신의 문제가 여기에있다 생각 : 당신은 당신의 구조의 크기에 의해 next_index 확장하고

int next_index = sizeof(struct myInfo) * ... 
*(queue + (next_index)) = info; 

그러나 이것은 그 두 번째에 의해 자동으로 수행 뭔가 성명서 - *(queue + (next_index))queue[next_index]과 같으며 후자는 K이후 C를 사용해온 모든 사람에게 더 읽기 쉽습니다.

void push(struct myInfo info) { 
    int next_index = (queue_size + queue_head) % MAX_QUEUE; 
    printf("Pushing %s to %d\n", info.data, next_index); 
    queue[next_index] = info; 
    queue_size++; 
} 

을 그리고 명심 :R 먼저 0에서 MAX_QUEUE-1에 값, 그래서 sizeof(struct myInfo)하여 곱셈을 제거하는 첫 번째 문을 변경하려고한다 즉

, next_index :-) 출판 되었음 결국 무한 루프에 queue_size이 넘칠 것입니다. 최종 생산 준비 코드에서 queue_size이 MAX_QUEUE 이상으로 증가하지 않았는지 확인해야 할 것입니까? 그렇습니다. 당신은 필요하지 않은, sizeof(struct myInfo)에 의해 next_index을 곱하여하고

int main(int argc, char *argv[]) 
{ 
     queue = (struct myInfo*) malloc(sizeof(struct myInfo) * MAX_QUEUE); 

     while (1) 
     { 
       struct myInfo info; /* Seems you're using C99 so we can declare here */ 
       strcpy(info.data, "hello"); 
       push(info); 
     } 
} 
+0

고마워, 그게 문제 야! 그리고 네, queue_size를 확인하고 큐가 가득 차면 경고하는 다른 코드가 있습니다. 이 경우 요인이되지 않았으므로 포함시키지 않았습니다. :) – Trevor

0
void push(struct myInfo info) { 
     int next_index = (queue_size + queue_head) % MAX_QUEUE; 
     printf("Pushing %s to %d\n", info.data, next_index); 
     queue[next_index] = info; 
     queue_size++; 
} 

또한, 당신은 buf 일시적인 것이 필요하지 않습니다. 포인터 유형에 추가 할 때, 옵셋은 가리키는 대상의 크기로 자동 계산됩니다. push()의 첫 번째 라인을 변경하면 충분합니다 :

int next_index = (queue_size + queue_head) % MAX_QUEUE; 
1

:

0
*(queue + (next_index)) = info; 

queuestruct myInfo에 대한 포인터입니다. 다음 주소를 얻으려면 그 주소에 1을 더하면됩니다. 주소는 char *입니다.

당신은 할 수 있습니다 :

*(queue + queue_size++) = info; 
+0

할 수 없다 : 큐는 원형이고 배열의 인덱스'queue_head'에서 시작한다. – Thomas

0

당신은 배열로 을 처리 할 수 ​​있으며 다음 항목 밀어 단순해야한다 : 당신의 고정 크기를 사용하고 있기 때문에

 
void push(struct myInfo info) { 
    if (queue_size < MAX_QUEUE) { 
    printf("Pushing %s to %d\n", info.data, queue_size); 
    queue[queue_size] = info; 
    queue_size++; 
    } else { 
    printf("ERROR: Queue is full.\n"); 
    /* alternatively you could have a queue_insertion_point 
     variable to keep track of where you are in the queue 
     and use that as your index into your array. You'd then 
     reset it to 0 (to wrap around) when it hit MAX_QUEUE. 
     You need to ensure you don't overwrite data currently 
     in the queue by comparing it against queue_head */ 
    } 
}