2011-10-18 4 views
0

다음과 같이 작은 바이너리 데이터를 저장하는 데 사용되는 큐를 만들었습니다. queue_read() 및 queue_del()은 읽기 및 삭제 작업을 수행하는 큐의 한쪽에서 작동합니다. queue_add()는 큐의 다른 쪽 끝에 데이터를 추가합니다. 이 코드를 다른 코드에서 사용하여 데이터를 저장하면 세그멘테이션 오류 문제가 발생합니다. 하지만 gdb를 사용하여 세분화 문제를 일으키는 원인을 찾을 수 없었습니다. 대부분의 시간은 malloc-> memalign 문제처럼 진행되지만 null 포인터는 찾을 수 없습니다. 이 코드를 개별적으로 테스트하면 문제를 찾을 수 없습니다. 구현에 문제가있는 경우 누군가가 지적 할 수 있다는 점이 좋습니다. 감사합니다큐 알고리즘을 사용한 분할 오류

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

struct queue_node { 
    struct queue_node *next; 
    unsigned char data; 
}; 

struct queue { 
    struct queue_node *first; 
    struct queue_node *last; 
}; 

/* initialize the queue */ 
void init_queue(struct queue *q) { 
    q->first = q->last = NULL; 
} 

/* check if the queue is empty or not */ 
int queue_empty_p(const struct queue *q) { 
    return q->first == NULL;  
} 

/* Reading 'len' bytes data from queue to buffer variable 'value' 
* 
* RETURNS bytes read which can be less than or equal to the requested 
* value of 'len' 
*/ 
int queue_read(struct queue *q, unsigned char *read_buffer, unsigned int len) { 
    unsigned int i; 
    struct queue_node *tmp = (struct queue_node *) malloc(
      sizeof(struct queue_node)); 

    tmp = q->first; 
    for (i = 0; i < len; i++) { 
     if (tmp == NULL) { 
      read_buffer[i] = 0; 
      return (i); 
     } 
     read_buffer[i] = tmp->data; 
     tmp = tmp->next; 
    } 
    return len; 
} 

/* Deleting specified no of bytes from queue. Usually done after queue_read() */ 
int queue_del(struct queue *q, unsigned int no_of_bytes) { 
    unsigned int i; 

    for (i = 0; i < no_of_bytes; i++) { 
     if (!q->first) { 
      return 1; 
     } 
     struct queue_node *tmp = q->first; 
     if (q->first == q->last) 
      q->first = q->last = NULL; 
     else 
      q->first = q->first->next; 

     free(tmp); 
    } 
    return 0; 
} 

/* Adding 'len' bytes of data contained in the variable 'value' to the queue */ 
int queue_add(struct queue *q, unsigned char *value, unsigned int len) { 

    struct queue_node *node; 
    unsigned int i; 

    for (i = 0; i < len; i++) { 
     node = (struct queue_node *) malloc(sizeof(struct queue_node)); 
     if (node == NULL) { 
      return 1; 
     } 
     node->data = *(value + i); 
     if (q->first == NULL) 
      q->first = q->last = node; 
     else { 
      q->last->next = node; 
      q->last = node; 
     } 
     node->next = NULL; 
    } 
    return 0; 
} 

int main() { 
    struct queue left_queue; 
    char *buffer = (char *)malloc(100); 
    int read_bytes; 

    strcpy(buffer, "This is a test"); 
    init_queue(&left_queue); 

    queue_add(&left_queue, (unsigned char *) buffer, strlen(buffer)); 

    queue_del(&left_queue, 3); 

    read_bytes = queue_read(&left_queue, (unsigned char *)buffer, 1500); 
    buffer[read_bytes]=0; 
    printf("Buffer: %s \nBytes read %d \n", (unsigned char *)buffer, read_bytes); 

    return 0; 
} 

편집 : Valgrind의의 gdb를 역 추적 출력

Program received signal SIGSEGV, Segmentation fault. 
[Switching to Thread 0xb6ef3b70 (LWP 2678)] 
0x0012f4df in memalign() from /usr/lib/libefence.so.0 
#0 0x0012f4df in memalign() from /usr/lib/libefence.so.0 
#1 0x0012f88b in malloc() from /usr/lib/libefence.so.0 
#2 0x08049576 in queue_add (q=0xb7f21fc8, 
    value=0xb7f2da28 "GET /wiki/Special:Search?search=rohc&sourceid=Mozilla-search HTTP/1.1\r\nHost: en.wikipedia.org\r\nUser-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.04 (lucid) Fire"..., 
    len=440) at pep_core.h:248 
#3 0x0804cc81 in fn_process_tcp() at pep_core.c:584 
#4 0x0013b96e in start_thread() from /lib/tls/i686/cmov/libpthread.so.0 
#5 0x00228a4e in clone() from /lib/tls/i686/cmov/libc.so.6 
#0 0x0012f4df in memalign() from /usr/lib/libefence.so.0 
No symbol table info available. 
#1 0x0012f88b in malloc() from /usr/lib/libefence.so.0 
No symbol table info available. 
#2 0x08049576 in queue_add (q=0xb7f21fc8, 
    value=0xb7f2da28 "GET /wiki/Special:Search?search=rohc&sourceid=Mozilla-search HTTP/1.1\r\nHost: en.wikipedia.org\r\nUser-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.04 (lucid) Fire"..., 
    len=440) at pep_core.h:248 
     node = 0xb661bff8 
     i = 245 
#3 0x0804cc81 in fn_process_tcp() at pep_core.c:584 
     ip_queue_table = 0xb7f2d9fc 
     tmp_ip_queue_table = 0x0 
     tcp_conn = 0xb7f21fa8 
     tmp_tcp_conn = 0x0 
     tcphdrs = 0xb7f2da14 
     iphdrs = 0xb7f2da00 
     packet_data = 0xb7f2da28 "GET /wiki/Special:Search?search=rohc&sourceid=Mozilla-search HTTP/1.1\r\nHost: en.wikipedia.org\r\nUser-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.04 (lucid) Fire"... 
     read_buffer = 0xb7f17a24 "" 
     read_bytes = 0 
     payload_size = 440 
     ret = 0 
     rawfd = 9 
     one = 1 
#4 0x0013b96e in start_thread() from /lib/tls/i686/cmov/libpthread.so.0 
No symbol table info available. 
#5 0x00228a4e in clone() from /lib/tls/i686/cmov/libc.so.6 
No symbol table info available. 

출력

난 당신이 제안 Valgrind의 실행 다음과 같은

Syscall param socketcall.sendto(msg) points to uninitialised byte(s) 

위의 오류가 4 볼 수 있어요 번 다음 메시지는

(210)
==3159== Process terminating with default action of signal 11 (SIGSEGV): dumping core 
==3159== Bad permissions for mapped region at address 0x5AD2FFC 
==3159== at 0x804962F: queue_read (pep_core.h:279) 
==3159== by 0x804D672: fn_thread_pep_left_sctp_client (pep_core.c:856) 
==3159== by 0x403D96D: start_thread (pthread_create.c:300) 
==3159== by 0x412AA4D: clone (clone.S:130) 
+2

segfault가 반드시 NULL 포인터로 인해 생성 된 것은 아닙니다. 당신은 gdb를 사용했다고 말했습니까? 세그 폴트 이후 백 트레이스를 제공 할 수 있습니까? – Florian

+0

문제가 두 번째 프로그램이 아닌 것이 확실합니까? 내 생각 엔 잘못된 길이를'queue_read'에 전달하고 뭔가를 덮어 쓰는 것입니다. 당신이 그랬던 것처럼. –

+0

valgrind로 테스트 해 보았습니까? 그렇다면 valgrind의 출력을 줄 수 있습니다. – tune2fs

답변

0

내가 코드를 이해하지만, 그것은 기본적 read 같은 queue_read 작품처럼 보인다 확실하지 경우, 즉, 그것은 전달 버퍼로 읽습니다.

char *buffer = (char *)malloc(100); 
[...] 
read_bytes = queue_read(&left_queue, (unsigned char *)buffer, 1500); 

은 단순히에 너무 많은 데이터를 읽고 버퍼가 너무 작습니까? 나는이 문제라고 생각

+0

입력 해 주셔서 감사합니다. 혼란스럽게해서 미안합니다. 예제로 100과 1500을주었습니다. 실제 경우에는 항상 1000 바이트입니다. queue_read()는 ** 전달 된 길이 값보다 작거나 같은 ** 바이트를 복사 할 수 있습니다.아래의 'tmp = q->를 먼저보십시오; (tmp == NULL) { _read_buffer [i] = 0;if (tmp == NULL) { 에 대한 (i = 0; i data; tmp = tmp-> next; } return len; ' 그래서 코드는 큐가 비어 있는지 여부를 검사하여 읽은 양을 반환합니다. – snibu

0
struct queue_node *tmp = (struct queue_node *) malloc(
     sizeof(struct queue_node)); 

tmp = q->first; 

, 무슨 일이 당신이 뭔가를 가리 키도록 포인터를 설정하는 것이 메모리를 사용하지 않고 다음 특정 주소에 메모리 블록을 할당하지만 것입니다. 따라서 메모리 누수가 발생합니다. 포인터에 값을 할당하면 포인터가 메모리의 다른 위치를 가리키는 대신 값을 복사하지 않습니다.