Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.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_Malloc_Structure - Fatal编程技术网

C 指针操作中未按预期打印结构变量的值

C 指针操作中未按预期打印结构变量的值,c,pointers,malloc,structure,C,Pointers,Malloc,Structure,在上面的程序中,为什么我得到“0”并且mycode函数中没有显示数据,它应该是“10”,并且应该打印“sample”,程序有什么问题?据我所知,当我们进行清理时,我没有作为引用传递,所以它不应该影响结构的本地副本。 请澄清我的疑问我认为您的问题在于清理(p) 在打印数据之前不应该这样做 据我所知,当我们进行清理时,我不会作为引用传递,所以它不应该影响结构的本地副本。请澄清我的疑问 你部分是对的。 在“清理”中,您只有一份p。将NULL赋值给它不会改变任何东西 但是您将globalp的值传递给函数

在上面的程序中,为什么我得到“0”并且mycode函数中没有显示数据,它应该是“10”,并且应该打印“sample”,程序有什么问题?据我所知,当我们进行清理时,我没有作为引用传递,所以它不应该影响结构的本地副本。
请澄清我的疑问

我认为您的问题在于清理(p) 在打印数据之前不应该这样做

据我所知,当我们进行清理时,我不会作为引用传递,所以它不应该影响结构的本地副本。请澄清我的疑问

你部分是对的。 在“清理”中,您只有一份
p
。将
NULL
赋值给它不会改变任何东西

但是您将global
p
的值传递给函数,然后调用
free
。 这不会改变
p
,但会释放指向的内存

调用
cleanup
后,不允许再次访问该内存位置

你期望得到什么

Hello, World!
p->a - 10
p.b - sample
p->a - 10
p.b - sample appenddata
p->a - 0
p.b - 
基于错误的假设。 您可以得到任何值,因为这是未定义的bahaviour

顺便说一句: 如果内存不是无效的,您将得到

10
sample
这是出于同样的原因


appenddata
中,您不会更改
p
,但会更改
p->b
,它在您离开函数后仍然存在。

为避免出现与
free
相关的警告,请将
添加到源代码,在清理过程中,您会清理结构数据并取消引用本地指针而不是主指针。因此,主指针变为悬挂指针

在演示中添加了一些printf:

10
sample appenddata
于是试图打印出指针悬空指向的垃圾

为了避免这种情况,你可以采取任何一种方法

将清除函数替换为宏

Hello, World!
p->a - 10
p.b - sample
p->a - 10
p.b - sample appenddata
Pointer Address before cleanup : 0x14a5020
Pointer Address before free : 0x14a5020
Pointer Address after free : (nil)
Pointer Address after cleanup : 0x14a5020
p->a 1- 0
p.b 2-  
或从清除函数返回指针

#define cleanup(p) free(p); p=NULL

您的程序有两个未定义的行为

第一个未定义的行为:

struct type
中,成员
b
作为
10
字符的数组:

MyType* cleanup(MyType* pointer);

....................
 /* set the values for p and do some stuff with it */
p = cleanup(p);
.......................

MyType* cleanup(MyType* pointer) {

  free(pointer);
  pointer = NULL;
  return pointer;
} 
在函数
appenddata()
中,将长度超过
10个字符的字符串复制到
b

char b[10];
访问超出边界的数组是未定义的行为

要解决此问题,请增加数组
b
,如b[50],并使用
strncpy
,这样可以控制要复制到目标的字符数。使用strncpy之前,请仔细阅读它

第二个未定义的行为:

当您释放一个动态分配的内存块时,它的生存期就结束了

来自C标准#6.2.4p2

对象的生存期是程序执行期间保证为其保留存储的部分。对象存在,具有恒定地址33),并在其整个生存期内保留其最后存储的值。34)如果对象在其生存期之外被引用,则行为未定义。当指针指向(或刚刚经过)的对象到达其生命周期结束时,指针的值变得不确定。 [我的重点]

在这里,您将在释放后访问
p

strcpy(p->b, "sample appenddata");
              ^^^^^^^^^^^^^^^^^
if(p!=NULL)
{

printf(“p->a-%d\n”,p->a);b);您正在跟踪
p
#include
。打开警告。即使在解决Keine注意到的问题后,
pointer=NULL;
cleanup
中是无意义的。所做的只是将本地指针变量设置为
NULL
,调用方提供的参数将保持不变(虽然它将保存一个现在悬空的无效指针值)。即使我在mycode函数中获取“MyType*p”的本地副本,我也会得到相同的结果!!!#Gerhardhhi如果您的
p
是全局
p
的副本,那么它将指向相同的内存并导致完全相同的问题。
strcpy(p->b, "sample appenddata");
              ^^^^^^^^^^^^^^^^^
  if(p != NULL)
  {
    printf("p->a - %d\n",p->a); << Why value I am getting is '0' here and 
    printf("p.b - %s\n",p->b);  << No value is printed here
  }