为什么分配内存后直接释放会出现访问冲突异常
Why the access violation exception when freeing directly after allocating memory
在释放一些指针时,我遇到了访问冲突。
为了知道发生了什么,我决定在代码的较早阶段要求释放指针,甚至在分配内存之后直接释放指针,但它仍然崩溃。
这意味着我的结构在内存中的处理方式存在严重错误。
我知道在以前版本的代码中,在一些变量的定义之前有一个关键字,但是那个关键字丢失了(它是 #define
子句的一部分我找不到了).
有谁知道这段代码有什么问题或者提到的关键字应该是什么?
typedef unsigned long longword;
typedef struct part_tag { struct part_tag *next;
__int64 fileptr;
word needcount;
byte loadflag,lock;
byte partdat[8192];
} part;
static longword *partptrs;
<keyword> part *freepart;
<keyword> part *firstpart;
void alloc_parts (void) {
part *ps;
int i;
partptrs = (longword*)malloc (number_of_parts * sizeof(longword)); // number... = 50
ps = (part*)&freepart;
for (i=0; i<number_of_parts; i++) {
ps->next = (struct part_tag*)malloc(sizeof(part));
partptrs[i] = (longword)ps->next;
ps = ps->next;
ps->fileptr = 0; ps->loadflag = 0; ps->lock = 0; ps->needcount = 0; // fill in "ps" structure
};
ps->next = nil;
firstpart = nil;
for (i=0; i<number_of_parts; i++) {
ps = (part*)partptrs[i];
free(ps); <-- here it already crashes at the first occurence (i=0)
};
}
提前致谢
在评论中有人问我为什么分配后直接释放指针。这不是程序最初的编写方式,但为了了解导致访问冲突的原因,我以这种方式重写了。
原文:
alloc_parts();
<do the whole processing>
free_parts();
为了分析访问冲突,我将 alloc_parts() 函数应用到我在那里编写的源代码摘录中。关键是,即使直接在分配内存之后,释放也会出错。这怎么可能?
与此同时我观察到另一个奇怪的现象:
在分配内存时,ps
的值似乎是 "complete" 地址值。在尝试释放内存时,ps
的值仅包含内存地址的最后一位数字。
Example of complete address : 0x00000216eeed6150
Example of address in freeing loop : 0x00000000eeed6150 // terminating digits are equal,
// so at least something is right :-)
此问题是由 longword
类型引起的:该类型似乎太小,无法容纳整个内存地址。我已将其替换为另一种类型 (unsigned long long
),但问题仍然存在。
终于苦了半天,问题解决了:
程序原本是32位的应用程序,也就是说原来的类型unsigned long
足以保留内存地址
但是,此程序现在被编译为 64 位应用程序,因此上述类型不再足够大以保留 64 位内存地址,因此已使用另一种类型来解决此问题:
typedef intptr_t longword;
这解决了问题。
@Andrew Henle:抱歉,我没有意识到你的评论包含了这个问题的实际解决方案。
在释放一些指针时,我遇到了访问冲突。
为了知道发生了什么,我决定在代码的较早阶段要求释放指针,甚至在分配内存之后直接释放指针,但它仍然崩溃。
这意味着我的结构在内存中的处理方式存在严重错误。
我知道在以前版本的代码中,在一些变量的定义之前有一个关键字,但是那个关键字丢失了(它是 #define
子句的一部分我找不到了).
有谁知道这段代码有什么问题或者提到的关键字应该是什么?
typedef unsigned long longword;
typedef struct part_tag { struct part_tag *next;
__int64 fileptr;
word needcount;
byte loadflag,lock;
byte partdat[8192];
} part;
static longword *partptrs;
<keyword> part *freepart;
<keyword> part *firstpart;
void alloc_parts (void) {
part *ps;
int i;
partptrs = (longword*)malloc (number_of_parts * sizeof(longword)); // number... = 50
ps = (part*)&freepart;
for (i=0; i<number_of_parts; i++) {
ps->next = (struct part_tag*)malloc(sizeof(part));
partptrs[i] = (longword)ps->next;
ps = ps->next;
ps->fileptr = 0; ps->loadflag = 0; ps->lock = 0; ps->needcount = 0; // fill in "ps" structure
};
ps->next = nil;
firstpart = nil;
for (i=0; i<number_of_parts; i++) {
ps = (part*)partptrs[i];
free(ps); <-- here it already crashes at the first occurence (i=0)
};
}
提前致谢
在评论中有人问我为什么分配后直接释放指针。这不是程序最初的编写方式,但为了了解导致访问冲突的原因,我以这种方式重写了。
原文:
alloc_parts();
<do the whole processing>
free_parts();
为了分析访问冲突,我将 alloc_parts() 函数应用到我在那里编写的源代码摘录中。关键是,即使直接在分配内存之后,释放也会出错。这怎么可能?
与此同时我观察到另一个奇怪的现象:
在分配内存时,ps
的值似乎是 "complete" 地址值。在尝试释放内存时,ps
的值仅包含内存地址的最后一位数字。
Example of complete address : 0x00000216eeed6150
Example of address in freeing loop : 0x00000000eeed6150 // terminating digits are equal,
// so at least something is right :-)
此问题是由 longword
类型引起的:该类型似乎太小,无法容纳整个内存地址。我已将其替换为另一种类型 (unsigned long long
),但问题仍然存在。
终于苦了半天,问题解决了:
程序原本是32位的应用程序,也就是说原来的类型unsigned long
足以保留内存地址
但是,此程序现在被编译为 64 位应用程序,因此上述类型不再足够大以保留 64 位内存地址,因此已使用另一种类型来解决此问题:
typedef intptr_t longword;
这解决了问题。
@Andrew Henle:抱歉,我没有意识到你的评论包含了这个问题的实际解决方案。