我正在制作一个程序,它需要C89中的多种类型的动态数组。我正在尝试创建一个支持自定义结构数据的动态数组的自己的实现。
然而,在使用我的动态数组实现时,我得到了堆缓冲区溢出,我不知道为什么。我似乎没有选角问题。我已经正确地分配并调整了动态数组的大小。我用了合适的尺码。我应该能够毫无问题地将结构添加到数组中。
这是包含动态数组和点结构的主C文件。堆缓冲区溢出发生在
dynamic_array_push
。注意:出于测试目的,我创建了
point_a
变量,因此在这种情况下没有制作动态数组的实际目的。
struct point {
int x;
int y;
const char* id;
};
int main() {
struct dynamic_array points = dynamic_array_create(sizeof(struct point));
struct point point_a = {1, 1, "point_a"};
size_t i;
dynamic_array_push(&points, (void*)&point_a); /* Heap buffer overflow here */
return 0;
}
这里是动态数组头文件,它包含创建和推送到动态数组的最小功能(不包括释放内存和弹出)。我已经找出了堆缓冲区溢出的原因,它发生在
memcpy
.
#define DYNAMIC_STARTING_SIZE 1
#define DYNAMIC_GROWTH_AMOUNT 1.5
struct dynamic_array {
void* data;
size_t amount;
size_t capacity;
size_t element_size;
};
struct dynamic_array dynamic_array_create(size_t element_size) {
struct dynamic_array dynamic_array;
dynamic_array.data = malloc(sizeof(DYNAMIC_STARTING_SIZE * element_size));
dynamic_array.amount = 0;
dynamic_array.capacity = DYNAMIC_STARTING_SIZE;
dynamic_array.element_size = element_size;
return dynamic_array;
}
void* dynamic_array_get(struct dynamic_array* dynamic_array, size_t index) {
if (index >= dynamic_array->amount) {
return NULL;
}
return ((unsigned char*)dynamic_array->data) + (index * dynamic_array->element_size);
}
void dynamic_array_push(struct dynamic_array* dynamic_array,
const void* element) {
unsigned char* destination =
(unsigned char*)dynamic_array->data +
dynamic_array->amount * dynamic_array->element_size;
if (dynamic_array->amount >= dynamic_array->capacity) {
dynamic_array->capacity =
(size_t)ceil(dynamic_array->capacity * DYNAMIC_GROWTH_AMOUNT);
dynamic_array->data =
realloc(dynamic_array->data,
dynamic_array->capacity * dynamic_array->element_size);
}
memcpy((void*)destination, element, dynamic_array->element_size); /* Heap buffer overflow here */
dynamic_array->amount++;
}
我打印出了内存地址位置的值,它们的大小应该是
点a
并在我的机器上获得了这些值:
Starting memory address: 0x502000000010
Destination memory address: 0x502000000010
Destination ending memory address: 0x502000000020 <- This is actually the address after the end
但地址清理程序显示的写入大小为16字节(如
const char* point_a
是8字节和2
int
s在我的机器上也是8个字节)的地址
0x502000000018
.
然后,我决定删除
const char* data
字段,修复了该问题。然后我测试并发现,任何指针,无论它在结构中的位置如何,都会导致堆溢出。
这个
destination
应该是正确的,因为我正在获取数据数组的位置,并添加数量乘以元素大小。这个
element
和
dynamic_array->element_size
位于正确的位置。当您第一次创建数组时,我也会适当地为数组数据分配内存,并在需要时重新分配(这在本文中并不重要,因为数组一旦创建就可以容纳一个值)。
我是否应该做其他事情来支持用于动态数组的结构中的指针,或者这里有其他问题?
与我的具体问题相似的问题,但我未能从中得到答案:
关于memcpy和动态数组的其他类似问题: