c - 在函数中创建的指针不正确
问题描述
我正在尝试在 C 中实现一个整数向量。在其中创建的向量指针vector_copy
大约为 0x3 或 0x2,这会导致分段错误。为什么会这样?这真的让我感到困惑,因为我有一个类似的实现vector_new
。
typedef struct vector {
int* items;
size_t size;
size_t max;
} vector;
vector* vector_copy(vector* v) {
vector* v2;
memcpy(v2->items,v->items,v->max * sizeof(int*));
if (v2->items == NULL) {
return NULL;
}
v2->size = v->size;
v2->max = v->max;
return v2;
}
vector* vector_new(size_t initial_capacity) {
vector* newv;
newv->items = malloc(initial_capacity * sizeof(int*));
if (newv->items == NULL) {
return NULL;
}
newv->size = 0;
newv->max = initial_capacity;
return newv;
}
int main() {
vector* v;
vector* v2;
v = vector_new(4);
//new vector with capacity 4 and size 0
vector_push(v, 1);
vector_push(v, 2);
//1 and 2 are pushed back
v2=vector_copy(v);
//vector is supposed to be copied
vector_free(v);
vector_free(v2);
return 0;
}
解决方案
vector* v2;
memcpy(v2->items,v->items,v->max * sizeof(int*));
这不是一个好主意。您基本上已经创建了一个指向v2
某个任意位置的指针(因为您尚未对其进行初始化),该指针值可能是之前某个操作(a)v2
留在堆栈上的任何值。然后,通过将字节复制到该任意位置,可能会发生各种奇怪的事情。
您实际上需要为这个新向量分配一些内存,例如:
vector *v2 = vector_new(v->max);
memcpy(v2->items, v->items, v->max * sizeof(int));
您(希望)还会注意到我已将 更改sizeof
为 useint
而不是int*
. 我怀疑这items
指向了前者的数组,在这种情况下这是正确的值。
所以下面的函数是一个更好的起点:
vector *vector_copy(vector* v) {
// Use vector_new to get empty one with exact same properties.
vector *v2 = vector_new(v->max);
if (v2 == NULL) return NULL;
// Copy data in to it and return.
memcpy(v2->items, v->items, v->max * sizeof(int));
v2->size = v->size;
return v2;
}
您的函数中也有完全相同的问题(没有结构分配和错误sizeof
)new
,可以通过以下方式解决:
vector *vector_new(size_t initial_capacity) {
// Allocate a vector structure, fail if no go.
vector *newv = malloc(sizeof(vector));
if (newv == NULL) return NULL;
// Allocate the data area, free structure and fail if no go.
newv->items = malloc(initial_capacity * sizeof(int));
if (newv->items == NULL) {
free(newv);
return NULL;
}
// Set up everything needed and return it.
newv->size = 0;
newv->max = initial_capacity;
return newv;
}
该功能基于 设置最大值这一事实使initial_capacity
您无需设置max
.vector_copy()
(a)我说“可能”是因为许多实现在重用堆栈帧内存区域方面的工作方式。但是,这绝不是保证,只有一种可能性。你应该假设它会有一些随机值,因此会表现得恰当(或不恰当,取决于你的观点)。
推荐阅读
- amazon-web-services - 没有 AWS 凭证的 Terraform 运行计划
- python - 如何有条件地将一个列表中的元组附加到另一个元组列表?
- c# - EF Core One to Many adding new object
- c# - 在 Any at = IsAvailable = !b.BorrowHistories.Any(h => h.ReturnDate == null) 下获得一条红线
- c - INI 文件阅读器功能正在向我的结构寻址错误的值,我该如何解决?
- mysql - 如何在查询中执行递归查询或子查询?
- reactjs - 如何设置 react-final-form onSubmit 值参数类型 TypeScript
- javascript - 如何处理按钮按下时的输入数据?
- reactjs - 如何在 Tabnav 上方添加标题
- python - 检查目标时出错:预期 activation_1 的形状为 (1,),但数组的形状为 (10,)