【问题标题】:treating allocated memory as a different type将分配的内存视为不同的类型
【发布时间】:2011-05-17 16:37:53
【问题描述】:

假设我分配了一些内存。

char* buffer = (char*)my_malloc(2062);

我将 char 值分配给之前定义的名为 header 的数组的前 14 个字节。

memcpy(buffer, header, 14);

然后我想把剩余的分配空间当作指向浮动的指针。

float* float_buffer = (float*)(buffer + 14);
some_function(float_buffer);

然后在稍后的某个时候,我需要将所有数据发送出去。

transmit(buffer);
my_free(buffer);

这是处理记忆的正确方法吗? float* 演员可以吗?我遇到了我失去价值并且没有得到正确结果的问题。 我的问题是: 如果您必须将分配的内存视为不同的类型,然后在处理结束时将其作为 char* 发送.....这是正确的方法吗?

我检查了 ptr 值,当它们是 float* 和 char* 时它们是相同的,但我没有得到正确的结果。

我的一个限制是我最初只能从静态缓冲区分配一块内存。因此,不允许将另一个 malloc 调用为不同的类型 (float*)。

【问题讨论】:

  • 听起来你有对齐问题;你能展示你看到的预期结果和实际错误吗?
  • 是的,这是对齐问题……我不知道。我可以从这里拿走。谢谢。

标签: c memory pointers


【解决方案1】:

要使这项工作(至少可移植),您必须(至少)确保 float_buffer 是 sizeof(float)-aligned。您可以通过分配 sizeof(float) - 1 个额外字节、观察 malloc 调用模 sizeof(float) 的结果并酌情忽略前几个字节来做到这一点。 (当然,您必须保留原始指针才能进行 free() 调用。)

不过,您可能不想这样做。听起来“缓冲区”的目的是积累要通过网络或类似方式发送的数据,并且浮点数将从其他地方复制进来。您真正应该做的是反过来:将缓冲区始终视为 char[],并在复制源浮点数时将它们重新解释为字符序列。那是

char* buffer = malloc(total_size);
char* float_start = buffer + header_size;
memcpy(float_start, (char*)float_source, sizeof(float) * float_count);
transmit(buffer, total_size);
free(buffer);

【讨论】:

  • 谢谢,是对齐问题。
【解决方案2】:

从概念上讲,这没问题 - 但您必须做一些额外的工作以确保它能够可靠地工作。

一个潜在的问题是您不能以float 的形式访问任意地址。可能有特定的对齐要求 - malloc() 返回的地址需要正确对齐才能作为任何类型访问,但是一旦您将 14 添加到该地址,所有赌注都将关闭(@ 除外987654323@).

为确保正确对齐,您必须确保添加到buffer 的地址是sizeof(float) 的倍数。您可以通过使用以下公式添加填充来做到这一点:

#define PAD_OFFSET(offset, type) ((offset) + sizeof(type) - 1) & ~(sizeof(type) - 1))

float *float_buffer = (float *)(buffer + PAD_OFFSET(14, float));

请注意,这将在您的字符和浮点数之间创建一个间隙 - 填充

或者,您可以定义struct,编译器会为您计算出填充。这使用了称为灵活数组成员的 C99 功能:

struct foo {
    char abc[14];
    float xyz[];
};

struct foo *buffer = malloc(2062);
memcpy(&buffer->abc, header, 14);
some_function(&buffer->xyz);
transmit(buffer); /* Presuming transmit() expects a void * parameter. */

如果您希望在没有填充的情况下这样做,您不能直接访问buffer 中的内存作为浮点数 - 您必须创建一个临时数组并将其复制到:

float temp[500]; /* Or whatever size */
some_function(&temp);
memcpy(buffer + 14, temp, sizeof temp);

【讨论】:

  • 谢谢,是对齐问题。
【解决方案3】:

我在这里推测,但由于 malloc 的原型是

void *malloc(size_t size);

您实际上是将 void* 类型的缓冲区转换为 char*,因此稍后将缓冲区的另一块转换为 float* 就可以了,只要您正确处理指针记帐即可。

【讨论】:

    猜你喜欢
    • 2018-11-24
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 2020-08-23
    • 2013-09-29
    • 2013-08-30
    • 2015-12-24
    • 1970-01-01
    相关资源
    最近更新 更多