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

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

ntdll!RtlIsZeroMemory releasing linked list memory in C [warning: Critical error detected c0000374]

问题

I've translated the code parts for you:

test.h

  1. typedef struct snPng_block {
  2. uint8_t size[4];
  3. size_t dataSize;
  4. uint8_t *data;
  5. uint8_t crc[4];
  6. struct snPng_block *next;
  7. } snPng_block;
  8. int snPng_new(snPng_block **obj, size_t length)
  9. {
  10. if (!length) {
  11. return snErr_ErrNullData;
  12. }
  13. snPng_block *head = NULL;
  14. snPng_block *ptr = NULL;
  15. size_t index;
  16. for (index = 0; index < length; ++index) {
  17. if (head == NULL) {
  18. if (!(head = (snPng_block *)malloc(sizeof(snPng_block)))) {
  19. return snErr_Memory;
  20. }
  21. ptr = head;
  22. } else {
  23. if (!(ptr->next = (snPng_block *)malloc(sizeof(snPng_block)))) {
  24. return snErr_Memory;
  25. }
  26. ptr = ptr->next;
  27. }
  28. }
  29. ptr->next = NULL;
  30. (*obj) = head;
  31. return snErr_OK;
  32. }
  33. int snPng_release(snPng_block **obj)
  34. {
  35. snPng_block *ptr = NULL;
  36. for (ptr = (*obj); ptr; ptr = ptr->next) {
  37. free(ptr);
  38. }
  39. return snErr_OK;
  40. }

test.c

  1. int main(int argc, char **argv)
  2. {
  3. snPng_block *block = NULL;
  4. snPng_new(&block, 9);
  5. snPng_block *ptr = NULL;
  6. snSize index;
  7. for (index = 0, ptr = block; ptr != NULL; ++index, ptr = ptr->next) {
  8. printf("%"PRIu64" node: %p\n", index + 1, ptr);
  9. }
  10. snPng_release(&block);
  11. return 0;
  12. }

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

  1. typedef struct snPng_block {
  2. uint8_t size[4];
  3. size_t dataSize;
  4. uint8_t *data;
  5. uint8_t crc[4];
  6. struct snPng_block *next;
  7. } snPng_block;
  8. int snPng_new(snPng_block **obj, size_t length)
  9. {
  10. if(!length) {
  11. return snErr_ErrNullData;
  12. }
  13. snPng_block *head = NULL;
  14. snPng_block *ptr = NULL;
  15. size_t index;
  16. for(index = 0; index &lt; length; ++index) {
  17. if(head == NULL) {
  18. if(!(head = (snPng_block *)malloc(sizeof(snPng_block)))) {
  19. return snErr_Memory;
  20. }
  21. ptr = head;
  22. } else {
  23. if(!(ptr-&gt;next = (snPng_block *)malloc(sizeof(snPng_block)))) {
  24. return snErr_Memory;
  25. }
  26. ptr = ptr-&gt;next;
  27. }
  28. }
  29. ptr-&gt;next = NULL;
  30. (*obj) = head;
  31. return snErr_OK;
  32. }
  33. int snPng_release(snPng_block **obj)
  34. {
  35. snPng_block *ptr = NULL;
  36. for(ptr = (*obj); ptr; ptr = ptr-&gt;next) {
  37. free(ptr);
  38. }
  39. return snErr_OK;
  40. }

test.c

  1. int main(int argc, char **argv)
  2. {
  3. snPng_block *block = NULL;
  4. snPng_new(&amp;block, 9);
  5. snPng_block *ptr = NULL;
  6. snSize index;
  7. for(index = 0, ptr = block; ptr != NULL; ++index, ptr = ptr-&gt;next) {
  8. printf(&quot;%&quot;PRIu64&quot; node: %p\n&quot;, index + 1, ptr);
  9. }
  10. snPng_release(&amp;block);
  11. return 0;
  12. }

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.

  1. Reading symbols from #output\main.exe...
  2. (gdb) r
  3. Starting program: E:\Projects\Shark_Coast\#output\main.exe
  4. [New Thread 13724.0x8ac]
  5. 1 node: 00000244171955F0
  6. 2 node: 0000024417195830
  7. 3 node: 0000024417195890
  8. 4 node: 000002441719ADA0
  9. 5 node: 000002441719AE00
  10. 6 node: 000002441719AE60
  11. 7 node: 000002441719AEC0
  12. 8 node: 000002441719AF20
  13. 9 node: 00000244171994F0
  14. warning: Critical error detected c0000374
  15. Thread 1 received signal SIGTRAP, Trace/breakpoint trap.
  16. 0x00007fff7ab2f633 in ntdll!RtlIsZeroMemory () from C:\WINDOWS\SYSTEM32\ntdll.dll
  17. (gdb) backtrace
  18. #0 0x00007fff7ab2f633 in ntdll!RtlIsZeroMemory () from C:\WINDOWS\SYSTEM32\ntdll.dll
  19. #1 0x00007fff7ab383f2 in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll
  20. #2 0x00007fff7ab386da in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll
  21. #3 0x00007fff7ab3e361 in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll
  22. #4 0x00007fff7aa55b43 in ntdll!RtlGetCurrentServiceSessionId () from C:\WINDOWS\SYSTEM32\ntdll.dll
  23. #5 0x00007fff7aa547b1 in ntdll!RtlFreeHeap () from C:\WINDOWS\SYSTEM32\ntdll.dll
  24. #6 0x00007fff781bf05b in ucrtbase!_free_base () from C:\WINDOWS\System32\ucrtbase.dll
  25. #7 0x00007ff7f3653480 in snPng_release (obj=&lt;optimized out&gt;) at includes/image/test.h:53
  26. #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,这是因为指针是通过引用传递给函数的。

相反,您需要编写如下示例:

  1. int snPng_release(snPng_block **obj)
  2. {
  3. while (*obj)
  4. {
  5. snPng_block *ptr = *obj;
  6. *obj = (*obj)->next;
  7. // 释放数据成员 data 所指向的内存
  8. // 如果它也是动态分配的,类似于 free(ptr->data);
  9. free(ptr);
  10. }
  11. return snErr_OK;
  12. }

调用函数后,主函数中声明的原始指针 block 将等于 NULL,如所需。

英文:

It seems the problem exists due to the incorrect function snPng_release

  1. int snPng_release(snPng_block **obj)
  2. {
  3. snPng_block *ptr = NULL;
  4. for(ptr = (*obj); ptr; ptr = ptr-&gt;next) {
  5. free(ptr);
  6. }
  7. return snErr_OK;
  8. }

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

  1. int snPng_release(snPng_block **obj)
  2. {
  3. while ( *obj )
  4. {
  5. snPng_block *ptr = *obj;
  6. *obj = ( *obj )-&gt;next;
  7. // free the memory pointed to by the data member data
  8. // if it also was dynamically allocated
  9. // like free( ptr-&gt;data );
  10. free( ptr );
  11. }
  12. return snErr_OK;
  13. }

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:

  1. for(ptr = (*obj); ptr; ptr = ptr->next) {
  2. free(ptr);
  3. }

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:

  1. for(ptr = (*obj); ptr;) {
  2. snPng_block *tmp = ptr->next;
  3. free(ptr);
  4. ptr = tmp;
  5. }
英文:

Your snPng_release function is accessing the freed block after having already freed it.

In this for loop:

  1. for(ptr = (*obj); ptr; ptr = ptr-&gt;next) {
  2. free(ptr);
  3. }

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:

  1. for(ptr = (*obj); ptr;) {
  2. snPng_block *tmp = ptr-&gt;next;
  3. free(ptr);
  4. ptr = tmp;
  5. }

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:

确定