ntdll!RtlIsZeroMemory 在 C 中释放链表内存 [警告:检测到关键错误 c0000374]

huangapple go评论73阅读模式
英文:

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 &lt; length; ++index) {
        if(head == NULL) {
            if(!(head = (snPng_block *)malloc(sizeof(snPng_block)))) {
                return snErr_Memory;
            }
            ptr = head;
        } else {
            if(!(ptr-&gt;next = (snPng_block *)malloc(sizeof(snPng_block)))) {
                return snErr_Memory;
            }
            ptr = ptr-&gt;next;
        }
    }

    ptr-&gt;next = NULL;
    (*obj) = head;

    return snErr_OK;
}

int snPng_release(snPng_block **obj)
{
    snPng_block *ptr = NULL;
    for(ptr = (*obj); ptr; ptr = ptr-&gt;next) {
        free(ptr);
    }

    return snErr_OK;
}

test.c

int main(int argc, char **argv)
{
    snPng_block *block = NULL;
    snPng_new(&amp;block, 9);
    snPng_block *ptr = NULL;
    snSize index;

    for(index = 0, ptr = block; ptr != NULL; ++index, ptr = ptr-&gt;next) {
        printf(&quot;%&quot;PRIu64&quot; node: %p\n&quot;, index + 1, ptr);
    }
    snPng_release(&amp;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=&lt;optimized out&gt;) at includes/image/test.h:53
#8  main (argc=&lt;optimized out&gt;, argv=&lt;optimized out&gt;) 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-&gt;next) {
        free(ptr);
    }

    return snErr_OK;
}

where there are used invalid pointers in the expression ptr = ptr-&gt;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 )-&gt;next;
        // free the memory pointed to by the data member data
        // if it also was dynamically allocated 
        // like free( ptr-&gt;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-&gt;next) {
    free(ptr);
}

After running free(ptr), in the next iteration it will try set ptr = ptr-&gt;next, but ptr has already been freed.

One solution might be to save a pointer to ptr-&gt;next before freeing it:

for(ptr = (*obj); ptr;) {
    snPng_block *tmp = ptr-&gt;next;
    free(ptr);
    ptr = tmp;
}

huangapple
  • 本文由 发表于 2023年5月14日 03:53:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76244623.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定