Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c指针问题_C_Pointers - Fatal编程技术网

c指针问题

c指针问题,c,pointers,C,Pointers,这只是我心中的一个疑问 下面是代码 main() { int *p,*q; int a =20; p = q; p = &a; free(p); printf("The values of p and q are %d and %d\n

这只是我心中的一个疑问

下面是代码

          main()
          {
                  int *p,*q;
                  int a =20;
                  p = q;
                  p = &a;
                  free(p);
                  printf("The values of p and q are %d and %d\n",*p,*q);
           }
我的疑问是,如果我们释放指针p,分配给该指针的内存将被释放并返回到可用内存池,因此在这种情况下,由于q也指向p,根据我的理解,取消引用q应该会产生错误。我说的对吗?? 我在DeV C++编译器中运行这个程序,我惊讶的是它显示了指针的值。 在这种情况下,我们是否将指针q称为悬挂指针

提前多谢
Maddy

如何从堆栈中释放内存


不计算

您试图在指向堆栈分配内存的指针上调用
free()
,这是未定义的行为,千万不要这样做。仅对从
malloc()
获取的指针调用
free()

a是一个自动变量,而applyinfree(p),其中p=&a是一个错误,您可能会在malloc其他内存时立即面对,因为您将其标记为不可用的空闲块内存。

您应该阅读有关指针的内容并更好地理解它们

q
是一个未初始化的指针,您正在分配
p
指向同一个未指定的内存区域

p = &a;
这没关系,现在
p
包含
a
的地址,但是
q
仍然未初始化

free(p);
a
存储在堆栈中,而不是堆中。本可以通过以下方式实现:

int *a = malloc(sizeof(int)); // allocates memory and stores location
*a = 20;                      // modifies allocated memory
p = a;                        // have a second pointer to the same zone
free(p);                      // frees the allocated memory: now dereferencing either p or a is a sin.

尝试
释放
未使用
malloc
calloc
realloc
获取的内存会导致未定义的结果。有时它会做一些愚蠢的事情,比如继续跑步,然后给你愚蠢的结果。有时它会做一些更有用的事情:

$ ./a.out
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x00007fff8393bd5c ***
======= Backtrace: =========
/lib/libc.so.6(+0x774b6)[0x7f7a30bc04b6]
./a.out[0x400526]
/lib/libc.so.6(__libc_start_main+0xfe)[0x7f7a30b67d8e]
./a.out[0x400439]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:03 675233                             /tmp/a.out
00600000-00601000 r--p 00000000 08:03 675233                             /tmp/a.out
00601000-00602000 rw-p 00001000 08:03 675233                             /tmp/a.out
00f04000-00f25000 rw-p 00000000 00:00 0                                  [heap]
7f7a30933000-7f7a30948000 r-xp 00000000 08:03 228559                     /lib/libgcc_s.so.1
7f7a30948000-7f7a30b47000 ---p 00015000 08:03 228559                     /lib/libgcc_s.so.1
7f7a30b47000-7f7a30b48000 r--p 00014000 08:03 228559                     /lib/libgcc_s.so.1
7f7a30b48000-7f7a30b49000 rw-p 00015000 08:03 228559                     /lib/libgcc_s.so.1
7f7a30b49000-7f7a30cc3000 r-xp 00000000 08:03 228962                     /lib/libc-2.12.1.so
7f7a30cc3000-7f7a30ec2000 ---p 0017a000 08:03 228962                     /lib/libc-2.12.1.so
7f7a30ec2000-7f7a30ec6000 r--p 00179000 08:03 228962                     /lib/libc-2.12.1.so
7f7a30ec6000-7f7a30ec7000 rw-p 0017d000 08:03 228962                     /lib/libc-2.12.1.so
7f7a30ec7000-7f7a30ecc000 rw-p 00000000 00:00 0                      
7f7a30ecc000-7f7a30eec000 r-xp 00000000 08:03 228501                     /lib/ld-2.12.1.so
7f7a310cc000-7f7a310cf000 rw-p 00000000 00:00 0
7f7a310ea000-7f7a310ec000 rw-p 00000000 00:00 0                      
7f7a310ec000-7f7a310ed000 r--p 00020000 08:03 228501                     /lib/ld-2.12.1.so
7f7a310ed000-7f7a310ee000 rw-p 00021000 08:03 228501                     /lib/ld-2.12.1.so
7f7a310ee000-7f7a310ef000 rw-p 00000000 00:00 0                      
7fff8391d000-7fff8393e000 rw-p 00000000 00:00 0                          [stack]
7fff839df000-7fff839e0000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted

我的C库很有帮助地给出了失败的地址,并且非常有帮助地转储了内存映射(这对我来说是新的!谢谢!),这让我很快看到地址在堆栈上。

尝试释放
p
这里调用的-您只能释放malloc(或calloc,或realloc,或strdup)中的内容。在本例中,您将释放指向堆栈变量
a
的指针,这是不允许的

这同样适用于取消引用
*q
-
q
中的值未初始化,因此取消引用也会导致未定义的行为。严格地说,
p=q
也是未定义的*,但在实践中,简单地复制未初始化变量的值本身往往不会引起太多问题(只是不要期望该值有意义)

当您调用未定义的行为时,任何事情都可能发生-这包括但不限于:

  • 马上坠毁
  • 后来在一些不相关的代码中崩溃
  • 在不崩溃的情况下损坏某些数据
  • 损坏磁盘上一些您认为安全的数据
  • 联系备份服务器并破坏备份
  • 允许触发错误的黑客控制你的计算机
  • 上述各项的任意组合
  • 有时,什么也没有
编译器不需要给出任何类型的有用错误消息,尽管在某些情况下可能会这样做

简而言之,不要这样做,但如果你这样做了,不要期望它以任何一种特定的方式破裂。这类东西有一种很有趣的破坏方式,看起来就像是代码中完全不同部分的bug


*-根据C99 6.2.6.1,如果C实现具有指针类型的陷阱表示,则变量的未指定初始值可能是陷阱表示,在这一点上,通过
q
lvalue读取它会调用未定义的行为。

这给了我在运行Valgrind时所期望的确切行为:

==8839== Invalid free() / delete / delete[]
==8839==    at 0x4024836: free (vg_replace_malloc.c:325)
==8839==    by 0x8048440: main (boom.c:10)
==8839==  Address 0xbe9a5164 is on thread 1's stack
我这么做是因为我很好奇,因为有几个人报告了同样的行为

p
(由
free()
解除引用)的地址被称为悬挂指针,因此对其进行的任何操作都是未定义的。我编译时没有优化(-O0)和调试符号(-g),以生成更好的说明,但无论如何它都会崩溃

正如预期的那样,正常运行程序只会产生分段错误。在valgrind下分析时,程序实际上完成(当
printf()
还取消引用爆炸指针时,会有其他投诉):

但这只是因为Valgrind抓住了SEGV


未定义的行为就是,未定义。这是可怕的“哇,在我的机器上工作!”错误的主要原因之一:)

不要这样做
free()
用于分配给
malloc()
(及其朋友)的内存。当您按照预期使用glibc在gccIt segfaults中运行时,将出现分段错误。我已经发布了一个为什么的插图(通过Valgrind)来说明为什么。如果我像first p=&a;然后当你说p=q时,你分配p,而不是q<如果您不使用
q=something
@leppie对代码进行初始化,那么code>q
将永远不会在您的代码中有效。Free实际上应该会释放p所指的内存。因此,当您删除q时,它应该正确地给出错误?如果我是,请更正我wrong@Maddy:
free
仅释放
malloc
分配的内存,对cve.mitre.org数据库的一个旧副本进行非常粗略的搜索,会发现软件中大约有60个漏洞是在释放和双重释放错误后使用的,可能还有另外4个导致漏洞的免费(空)错误。请确保您了解
malloc()
free()
的正确用法。
==8839== Invalid free() / delete / delete[]
==8839==    at 0x4024836: free (vg_replace_malloc.c:325)
==8839==    by 0x8048440: main (boom.c:10)
==8839==  Address 0xbe9a5164 is on thread 1's stack
==8839== Use of uninitialised value of size 4
==8839==    at 0x8048445: main (boom.c:11)
==8839==
The values of p and q are 20 and 459916161
==8839==
==8839== HEAP SUMMARY:
==8839==     in use at exit: 0 bytes in 0 blocks
==8839==   total heap usage: 0 allocs, 1 frees, 0 bytes allocated