calloc 并使用 c 将数据复制到内存区域

发布于 2024-08-20 19:47:46 字数 1140 浏览 5 评论 0原文

我正在尝试分配一块内存,然后将数据复制到该空间中。我编写了这个简单的程序,但它没有达到我的预期。有人可以指出我的错误推理吗?

谢谢。

#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(应该是 22 而不是 15)

感谢大家的帮助,但我刚刚遇到了下一个障碍! 本练习的重点是通过 udp 向另一台主机发送一些数据。在调用 sendto() 之前,我查看了 bufptr 的内容,一切看起来都很好,并且发送似乎进行得很顺利。另一方面(我在 127.0.0.1 上运行客户端/服务器)我只收到“crap”。我调用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));

I'm trying to allocate a block of memory and then copy data into that space. I made this simple program and it doesn't do what I expect it to do. Could someone please point out my faulty reasoning.

Thanks.

#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));
}

What it prints out is the following:
bufptr11: 11
bufptr22: 15 (this should be 22 and not 15)

Thanks for all the help everybody, but I just ran into my next snag!
The whole point of this exercise is to send some data via udp to another host. I look at the content of the bufptr before I call sendto(), everything looks fine and the sending seems to go well. On the other side (I'm running client/server on 127.0.0.1) I just receive "crap". I call recvfrom(s_fd, bufptr, buflen, etc). I use the same calloc call for allocating memory for bufptr. There is the right amount of data being returned from this call, but the content of it is all just rubbish!

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));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

赤濁 2024-08-27 19:47:46


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

16 个字节分开,而我总共只分配了 8 个字节!比 bufptr[1] 更有用的提醒比看起来更有用。

这是一种可怕的错误,通常一开始不会显现出来,然后当您修改不相关的代码时就会开始导致崩溃。 valgrind 会捕获它。


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

EDIT: Much more insidious than the parens is the fact (which I obviously missed at first) that you are actually overdoing the pointer arithmetic. The compiler already adjusts bufptr + x to be bufptr + (x * sizeof(int)) bytes. So when you do bufptr + sizeof(int) you are actually overshooting the allocated memory.

You can see this with:

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

E.g. for me (32-bit machine) it outputs:

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

16 bytes apart, when I only allocated 8 total! A reminder than bufptr[1] is more useful than it looks.

This is the kind of horrible bug that often doesn't manifest at first, then starts causing crashes when you modify unrelated code. valgrind will catch it.

ㄖ落Θ余辉 2024-08-27 19:47:46
printf("bufptr22: %d\n", *bufptr+sizeof(int));

这被解释为 (*bufptr) + sizeof(int)。这给你 11 + 4 等于你看到的 15。

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

如果你想找回 22,这就是你所追求的。

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

That's being interpreted as (*bufptr) + sizeof(int). Which gives you 11 + 4 to make the 15 you're seeing.

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

That's what you're after if you're trying to get the 22 back.

少年亿悲伤 2024-08-27 19:47:46

试试这些:

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 +

Try these:

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 +
荆棘i 2024-08-27 19:47:46

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

是错误的,因为当您添加到指针时,您添加的单位是指针所指向的类型的大小。在本例中为int。所以不需要涉及sizeof,直接使用“对象”(int)的数量即可:

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

另外,最好使用指针而不是重复类型名称,如果它将来发生变化,这可以保护您:

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

在后一种情况下,使用目标指针的大小通常是一个好主意,因为这可以保护您(至少一点)不被覆盖源指针类型是否应更改。它们当然应该是相同的,但仍然如此。

This:

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

is wrong, since when you add to a pointer, you add in units of the size of the type the pointer is pointing at. In this case, int. So there's no need to involve sizeof, just use the number of "objects" (ints) directly:

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

Also, it's better to use the pointer rather than repeating the type name, this protects you if it should change in the future:

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

In the latter case, it's generally a good idea to use the size of the destination pointer, since that protects you (at least a bit) against overwrite if the source pointer type should change. They should of course be the same, but still.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文