c - 临时为算术转换 void* 的正确方法是什么?

标签 c valgrind memcpy void-pointers pointer-arithmetic

我是 C 新手,但当了几年程序员,所以我正在尝试通过学习 C 来学习 C 语言,方法是从 2008 年开始学习斯坦福大学的类(class)并做 Assignment 3关于 C 中的 vector 。

它基本上只是一个通用数组,所以数据作为 void * 保存在结构中。编译器标志 -Wpointer-arith 已打开,所以我不能做 arithmetic (我明白其中的原因)。

围绕数据的结构不能知道数据是什么类型,以便它对调用者是通用的。

为了简化事情,我正在尝试以下代码:

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

typedef struct {
    void *data;
    int aindex;
    int elemSize;
} trial;

void init(trial *vector, int elemSize)
{
    vector->aindex = 0;
    vector->elemSize = elemSize;
    vector->data = malloc(10 * elemSize);
}

void add(trial *vector, const void *elemAddr)
{
    if (vector->aindex != 0)
        vector->data = (char *)vector->data + vector->elemSize;

    vector->aindex++;
    memcpy(vector->data, elemAddr, sizeof(int));

}

int main()
{
    trial vector;
    init(&vector, sizeof(int));

    for (int i = 0; i < 8; i++)
        {add(&vector, &i);}

    vector.data = (char *)vector.data - ( 5 * vector.elemSize);
    printf("%d\n", *(int *)vector.data);
    printf("%s\n", "done..");

    free(vector.data);
    return 0;
}

然而,我在 free 中得到了一个错误 free(): invalid pointer。所以我在上面运行 valgrind 并收到以下信息:

==21006==  Address 0x51f0048 is 8 bytes inside a block of size 40 alloc'd
==21006==    at 0x4C2CEDF: malloc (vg_replace_malloc.c:299)
==21006==    by 0x1087AA: init (pointer_arithm.c:13)
==21006==    by 0x108826: main (pointer_arithm.c:29)

此时我的猜测是我没有正确执行 char*,或者可能使用了 memcpy incorrectly

最佳答案

发生这种情况是因为您向 vector 添加了八个元素,然后在尝试 free 之前将指针“回滚”仅五步。您可以通过使用 vector->aindex 来决定要展开多少索引来轻松解决这个问题。

然而,问题的根本原因是您修改了vector->data。您应该首先避免修改它,而是依赖于 add 函数内的临时指针:

void add(trial *vector, const void *elemAddr, size_t sz) {
    char *base = vector->data;
    memcpy(base + vector->aindex*sz, elemAddr, sz);
    vector->aindex++;
}

注意sz的使用,需要将sizeof(int)传给它。

代码中的另一个问题是当您通过将 vector.data 转换为 int* 进行打印时。这可能会奏效,但更好的方法是编写类似的 read 函数来提取数据。

关于c - 临时为算术转换 void* 的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50490069/

相关文章:

c - 为什么我的追加函数不再写入文件

c++ - 了解 Valgrind 的输出

c++ - 将uint32_ts和uint_8ts写入char文件,然后将它们转换回uint32_ts和uint_8ts

c - gcc 编译 c++ 时不带任何标志

c - 在 C 文件中读取(并转换)矩阵

c - 为什么 Valgrind 在错误的地方给出错误?

c++ - 流式加载和非 USWC 内存

c++ - 为什么 memcpy 无法正常运行?

将一行函数转换为c中的宏

c - 为什么我的程序会自动释放东西?