英文:
ntdll!RtlIsZeroMemory releasing linked list memory in C [warning: Critical error detected c0000374]
问题
I've translated the code parts for you:
test.h
typedef struct snPng_block {
uint8_t size[4];
size_t dataSize;
uint8_t *data;
uint8_t crc[4];
struct snPng_block *next;
} snPng_block;
int snPng_new(snPng_block **obj, size_t length)
{
if (!length) {
return snErr_ErrNullData;
}
snPng_block *head = NULL;
snPng_block *ptr = NULL;
size_t index;
for (index = 0; index < length; ++index) {
if (head == NULL) {
if (!(head = (snPng_block *)malloc(sizeof(snPng_block)))) {
return snErr_Memory;
}
ptr = head;
} else {
if (!(ptr->next = (snPng_block *)malloc(sizeof(snPng_block)))) {
return snErr_Memory;
}
ptr = ptr->next;
}
}
ptr->next = NULL;
(*obj) = head;
return snErr_OK;
}
int snPng_release(snPng_block **obj)
{
snPng_block *ptr = NULL;
for (ptr = (*obj); ptr; ptr = ptr->next) {
free(ptr);
}
return snErr_OK;
}
test.c
int main(int argc, char **argv)
{
snPng_block *block = NULL;
snPng_new(&block, 9);
snPng_block *ptr = NULL;
snSize index;
for (index = 0, ptr = block; ptr != NULL; ++index, ptr = ptr->next) {
printf("%"PRIu64" node: %p\n", index + 1, ptr);
}
snPng_release(&block);
return 0;
}
I hope this helps!
英文:
I am trying to write data with a linked list structure. After writing the function used to apply memory for each node in the linked list, I started writing the function used to release memory for each node in the linked list, but it encountered an error.
test.h
typedef struct snPng_block {
uint8_t size[4];
size_t dataSize;
uint8_t *data;
uint8_t crc[4];
struct snPng_block *next;
} snPng_block;
int snPng_new(snPng_block **obj, size_t length)
{
if(!length) {
return snErr_ErrNullData;
}
snPng_block *head = NULL;
snPng_block *ptr = NULL;
size_t index;
for(index = 0; index < length; ++index) {
if(head == NULL) {
if(!(head = (snPng_block *)malloc(sizeof(snPng_block)))) {
return snErr_Memory;
}
ptr = head;
} else {
if(!(ptr->next = (snPng_block *)malloc(sizeof(snPng_block)))) {
return snErr_Memory;
}
ptr = ptr->next;
}
}
ptr->next = NULL;
(*obj) = head;
return snErr_OK;
}
int snPng_release(snPng_block **obj)
{
snPng_block *ptr = NULL;
for(ptr = (*obj); ptr; ptr = ptr->next) {
free(ptr);
}
return snErr_OK;
}
test.c
int main(int argc, char **argv)
{
snPng_block *block = NULL;
snPng_new(&block, 9);
snPng_block *ptr = NULL;
snSize index;
for(index = 0, ptr = block; ptr != NULL; ++index, ptr = ptr->next) {
printf("%"PRIu64" node: %p\n", index + 1, ptr);
}
snPng_release(&block);
return 0;
}
The following are the results of my debugging using GDB tools.<br>
I don't quite understand why this program generates errors because I check if each node points to an NULL address before releasing it.
Reading symbols from #output\main.exe...
(gdb) r
Starting program: E:\Projects\Shark_Coast\#output\main.exe
[New Thread 13724.0x8ac]
1 node: 00000244171955F0
2 node: 0000024417195830
3 node: 0000024417195890
4 node: 000002441719ADA0
5 node: 000002441719AE00
6 node: 000002441719AE60
7 node: 000002441719AEC0
8 node: 000002441719AF20
9 node: 00000244171994F0
warning: Critical error detected c0000374
Thread 1 received signal SIGTRAP, Trace/breakpoint trap.
0x00007fff7ab2f633 in ntdll!RtlIsZeroMemory () from C:\WINDOWS\SYSTEM32\ntdll.dll
(gdb) backtrace
#0 0x00007fff7ab2f633 in ntdll!RtlIsZeroMemory () from C:\WINDOWS\SYSTEM32\ntdll.dll
#1 0x00007fff7ab383f2 in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll
#2 0x00007fff7ab386da in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll
#3 0x00007fff7ab3e361 in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll
#4 0x00007fff7aa55b43 in ntdll!RtlGetCurrentServiceSessionId () from C:\WINDOWS\SYSTEM32\ntdll.dll
#5 0x00007fff7aa547b1 in ntdll!RtlFreeHeap () from C:\WINDOWS\SYSTEM32\ntdll.dll
#6 0x00007fff781bf05b in ucrtbase!_free_base () from C:\WINDOWS\System32\ucrtbase.dll
#7 0x00007ff7f3653480 in snPng_release (obj=<optimized out>) at includes/image/test.h:53
#8 main (argc=<optimized out>, argv=<optimized out>) at test\test.c:29
答案1
得分: 3
问题似乎是由于不正确的函数 snPng_release
导致的,其中在删除指针所指向的内存后,在表达式 ptr = ptr->next
中使用了无效指针。
此外,在调用函数后,原始指针在表达式 *obj
中引用,将不等于 NULL
,这是因为指针是通过引用传递给函数的。
相反,您需要编写如下示例:
int snPng_release(snPng_block **obj)
{
while (*obj)
{
snPng_block *ptr = *obj;
*obj = (*obj)->next;
// 释放数据成员 data 所指向的内存
// 如果它也是动态分配的,类似于 free(ptr->data);
free(ptr);
}
return snErr_OK;
}
调用函数后,主函数中声明的原始指针 block
将等于 NULL
,如所需。
英文:
It seems the problem exists due to the incorrect function snPng_release
int snPng_release(snPng_block **obj)
{
snPng_block *ptr = NULL;
for(ptr = (*obj); ptr; ptr = ptr->next) {
free(ptr);
}
return snErr_OK;
}
where there are used invalid pointers in the expression ptr = ptr->next
after deleting memory pointed to by the pointers.
Also after calling the function the original pointer referred to by the expression *obj
will not be equal to NULL
as it is required because the pointer is passed to the function by reference.
Instead you need to write for example
int snPng_release(snPng_block **obj)
{
while ( *obj )
{
snPng_block *ptr = *obj;
*obj = ( *obj )->next;
// free the memory pointed to by the data member data
// if it also was dynamically allocated
// like free( ptr->data );
free( ptr );
}
return snErr_OK;
}
After calling the function the original pointer block
declared in main will be equal to NULL
as required.
答案2
得分: 1
Your snPng_release
function is accessing the freed block after having already freed it.
In this for loop:
for(ptr = (*obj); ptr; ptr = ptr->next) {
free(ptr);
}
After running free(ptr)
, in the next iteration, it will try to set ptr = ptr->next
, but ptr
has already been freed.
One solution might be to save a pointer to ptr->next
before freeing it:
for(ptr = (*obj); ptr;) {
snPng_block *tmp = ptr->next;
free(ptr);
ptr = tmp;
}
英文:
Your snPng_release
function is accessing the freed block after having already freed it.
In this for loop:
for(ptr = (*obj); ptr; ptr = ptr->next) {
free(ptr);
}
After running free(ptr)
, in the next iteration it will try set ptr = ptr->next
, but ptr
has already been freed.
One solution might be to save a pointer to ptr->next
before freeing it:
for(ptr = (*obj); ptr;) {
snPng_block *tmp = ptr->next;
free(ptr);
ptr = tmp;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论