2011-10-18 10 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; 
} 

EDIT:あなたが提案して

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

以下、上記のエラーが4見られてしまったように私はvalgrindの走った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. 

出力時間とその後のメッセージ

==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

問題は2番目のプログラムではないと確信していますか?私の推測では、あなたは '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(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; 

私は何が起こることは、あなたが何か他のものを指すようにポインタを設定し、特定のアドレスのメモリのブロックを割り当てるが、その後のではなく、そのメモリを使用することで、これは問題だと思います。したがって、メモリリーク。そのような値をポインタに割り当てると、ポインターがメモリ内の別の場所を指すのではなく、値をコピーしないことを忘れないでください。

関連する問題