我正在嘗試撰寫一組函式來支持動態分配的陣列,其中結構包含陣列和其他元資料。目標是將函式回傳給用戶,并且可以從函式中呼叫結構資訊。代碼似乎作業得很好,直到我得到從堆中釋放記憶體的函式。由于我不明白的原因,代碼因分段錯誤而失敗,這表明函式中的變數vec未free_vector指向正確的地址。但是,我已經使用列印陳述句驗證它指向正確的地址。我希望有人可以幫助我理解為什么該free_vector功能不起作用,特別是free命令。我的代碼和實作如下所示。
typedef struct
{
size_t allocated_length;
size_t active_length;
size_t num_bytes;
char *vector;
} Vector;
void *init_vector(size_t num_indices, size_t num_bytes) {
// Allocate memory for Vector struct
Vector *vec = malloc(sizeof(*vec));
vec->active_length = 0;
vec->num_bytes = num_bytes;
// Allocate heap memory for vector
void *ptr = malloc(num_bytes * num_indices);
if (ptr == NULL) {
printf("WARNING: Unable to allocate memory, exiting!\n");
return &vec->vector;
}
vec->allocated_length = num_indices;
vec->vector = ptr;
return &vec->vector;
}
// --------------------------------------------------------------------------------
int push_vector(void *vec, void *elements, size_t num_indices) {
Vector *a = get_vector_data(vec);
if(a->active_length num_indices > a->allocated_length) {
printf("TRUE\n");
size_t size = (a->allocated_length num_indices) * 2;
void *ptr = realloc(a->vector, size * a->num_bytes);
if (ptr == NULL) {
printf("WARNING: Unable to allocate memory, exiting!\n");
return 0;
}
a->vector = ptr;
a->allocated_length = size;
}
memcpy((char *)vec a->active_length * a->num_bytes, elements,
num_indices * a->num_bytes);
a->active_length = num_indices;
return 1;
}
// --------------------------------------------------------------------------------
Vector *get_vector_data(void *vec) {
// - The Vector struct has three size_t variables that proceed the vector
// variable. These variables consume 24 bytes of daya. THe code below
// points backwards in memory by 24 bytes to the beginning of the Struct.
char *a = (char *)vec - 24;
return (Vector *)a;
}
// --------------------------------------------------------------------------------
void free_vector(void *vec) {
// Free all Vector struct elements
Vector *a = get_vector_data(vec);
// - This print statement shows that the variable is pointing to the
// correct data.
printf("%d\n" ((int *)vec)[2]);
// The function fails on the next line and I do not know why
free(a->vector);
a->vector = NULL;
a->allocated_length = 0;
a->active_length = 0;
a->num_bytes = 0;
}
int main() {
int *a = init_vector(3, sizeof(int));
int b[3] = {1, 2, 3};
push_vector(a, b, 3);
// The code begins to fails here
free_vector(a);
}
uj5u.com熱心網友回復:
該程式存在未定義行為。
from 的回傳值init_vector是 typechar **的指標,指標指向字符,
return &vec->vector;
轉換為void *.
在main中,該值被轉換為int *
int *a = init_vector(3, sizeof(int));
void *然后,此值在傳遞給時轉換回push_vector.
在push_vector中,此值被強制轉換為 achar *以執行指標運算
memcpy((char *)vec a->active_length * a->num_bytes, elements,
num_indices * a->num_bytes);
malloc其中此操作會覆寫成員中包含的原始指標vector。
在我的系統上,這會嘗試從結構中成員int的位置開始將 12 個位元組(三個)寫入記憶體。vectorVector
Vector *vec
| &vec->vector
| |
v v
------ ------ ------ ------ -----
|size_t|size_t|size_t|char *|?????|
------ ------ ------ ------ -----
這溢位了,就像sizeof (char *)在8我的系統上一樣。
這是寫入資料的錯誤位置。寫入資料的正確位置是*(char **) vec- 或只是a->vector.
如果寫入沒有直接使程式崩潰(UB),這肯定會導致free傳遞的指標值不是由malloc,calloc或realloc, 或指標值回傳的NULL。
另外:在free_vector中,這個值也被轉換為int *
printf("%d\n", ((int *)vec)[2]); /* added a missing semi-colon. */
此外,尚不清楚是否free_vector應該釋放原始分配,或者只是釋放vector成員。您確實竭盡全力將此處的結構歸零。
盡管如此,您仍然存在記憶體泄漏 - 盡管很小。
void free_vector(void *vec) {
Vector *a = get_vector_data(vec);
/* ... */
free(a); /* This has to happen at some point. */
}
請注意,您應該使用它offsetof來計算成員在結構中的位置。的靜態偏移量24假設有兩件事可能不成立:
sizeof (size_t)總是8(實際最小值sizeof (size_t)是2),并且- 該結構不包含滿足對齊的填充(這似乎很可能給定形式,但并非嚴格正確)。
您在評論中鏈接的源使用靈活的陣列成員,而不是指標成員,這意味著整個資料(分配大小和向量)都存盤在連續的記憶體中。這就是為什么&操作員在這個實作中產生一個有效的位置來復制資料。
(旁白:鏈接的實作似乎被破壞了,因為有效地使用sizeof從指向靈活陣列成員(例如,&((vector_container *) pointer_to_flexible_member)[-1])的指標獲取容器結構的基礎,這沒有考慮尾隨填充的可能性,這將導致比預期更大的偏移量。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/496571.html
下一篇:c中函式中的多指標
