2

メモリのブロックを割り当ててから、その領域にデータをコピーしようとしています。この単純なプログラムを作成しましたが、期待どおりの動作をしません。誰かが私の間違った推論を指摘してくれませんか。

ありがとう。

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

void main(void)
{
int t1 = 11;
int t2 = 22;
int *bufptr;

bufptr = calloc(2, sizeof(int));
if(bufptr == NULL)
{
    fprintf(stderr, "Out of memory, exiting\n");
    exit(1);
}

memcpy(bufptr, &t1, sizeof(int));
memcpy((bufptr+sizeof(int)), &t2, sizeof(int));

printf("bufptr11: %d\n", *bufptr);
printf("bufptr22: %d\n", *bufptr+sizeof(int));
}

出力される内容は次のとおりです:
bufptr11: 11
bufptr22: 15 (これは 15 ではなく 22 である必要があります)

みんな助けてくれてありがとう。この演習の要点は、udp を介して別のホストにデータを送信することです。sendto() を呼び出す前に bufptr の内容を見てみると、問題なく送信できているようです。反対側(127.0.0.1でクライアント/サーバーを実行しています)では、「がらくた」を受け取ります。recvfrom(s_fd、bufptr、buflen など) を呼び出します。同じ calloc 呼び出しを使用して、bufptr にメモリを割り当てます。この呼び出しから適切な量のデータが返されますが、その内容はすべてゴミです!

bufptr = calloc(2, sizeof(int));
if(bufptr == NULL)
{
   fprintf(stderr, "Out of memory, exiting\n");
   exit(1);
}

buflen = 2*sizeof(int);

rc = recvfrom(sd, bufptr, buflen, 0, (struct sockaddr *)&serveraddr, &serveraddrlen);
printf("t2: %d\n", *bufptr);
printf("t3: %d\n", *(bufptr+1));
4

4 に答える 4

5

printf( "bufptr22:%d \ n"、*(bufptr + sizeof(int)));

編集:親よりもはるかに陰湿なのは、あなたが実際にポインタ演算をやり過ぎているという事実です(私は最初は明らかに見逃していました)。コンパイラはすでにbufptr+xをbufptr+(x * sizeof(int))バイトに調整しています。したがって、bufptr + sizeof(int)実際に割り当てられたメモリをオーバーシュートしていることになります。

あなたはこれを見ることができます:

printf("bufptr: %p\n", bufptr);
printf("bufptr + sizeof(int): %p\n", bufptr + sizeof(int));

たとえば、私(32ビットマシン)の場合、次のように出力されます。

bufptr: 0x876f008
bufptr + sizeof(int): 0x876f018

合計8バイトしか割り当てなかった場合、16バイト離れています。bufptr[1]見た目よりも便利なリマインダー。

これは恐ろしいバグの一種で、最初は現れないことが多く、無関係のコードを変更するとクラッシュを引き起こし始めます。 valgrindがそれをキャッチします。

于 2010-02-03T11:49:32.960 に答える
2
printf("bufptr22: %d\n", *bufptr+sizeof(int));

これは、(* bufptr)+ sizeof(int)として解釈されます。これにより、11 + 4が得られ、表示されている15になります。

printf("bufptr22: %d\n", *(bufptr+sizeof(int)));

あなたが22を取り戻そうとしているなら、それはあなたが求めているものです。

于 2010-02-03T11:50:45.087 に答える
1

これらを試してください:

memcpy(bufptr, &t1, sizeof(int)); // copy 11 into the first element of the array.
memcpy(bufptr+1, &t2, sizeof(int)); // bufptr+1 will point to the next int of the array.

printf("bufptr11: %d\n", *bufptr);
printf("bufptr22: %d\n", *(bufptr+1)); // parenthesis needed as * has higher precedence than +
于 2010-02-03T11:53:46.420 に答える
0

これ:

memcpy((bufptr+sizeof(int)), &t2, sizeof(int));

ポインターに追加するときは、ポインターが指している型のサイズの単位で追加するため、間違っています。この場合、int. したがって、 を含める必要はありませんsizeof。「オブジェクト」( ints) の数を直接使用するだけです。

memcpy(bufptr + 1, &t2, sizeof(int));

また、型名を繰り返すよりもポインターを使用することをお勧めします。これにより、将来変更された場合に保護されます。

memcpy(bufptr + 1, &t2, sizeof *bufptr);

後者の場合、ソース ポインターの型が変更された場合に (少なくとも少しは) 上書きから保護されるため、通常は宛先ポインターのサイズを使用することをお勧めします。もちろん、それらは同じである必要がありますが、それでもなおです。

于 2010-02-03T11:56:44.900 に答える