LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 694|回复: 6

请教C中关于内存的问题

[复制链接]
发表于 2006-1-8 11:12:15 | 显示全部楼层 |阅读模式
看了《高质量C++/C编程》中关于内存问题的举例,小弟对两个例子有点不解,请高手解惑
例子如下:
1,void getmemory(char *p)
     {
           p = (char*)malloc(100);
      }
     void test(void)
     {
          char *str = NULL;
          getmemory(str);
          strcpy(str, "hello);
          printf(str);
       }
执行这个例子,程序会崩溃,原文解释是getmemory函数不能传递动态函数,所以str一直是NULL,这样就导致程序崩溃。可是下面一个例子却是可以正确运行:
2,void getmemory(char **p)
     {
           *p = (char*)malloc(100);
      }
     void test(void)
     {
          char *str = NULL;
          getmemory(&str);
          strcpy(str, "hello);
          printf(str);
       }
我不明白的是两个例子中函数的形参都是指针,只是一个是指针,一个二重指针,为什么一个不可以传递动态内存,而另一个就可以呢?
另外,我发现,若在第二个版本的getmemory函数里面对p所指的内存区进行写操作,比如strcpy,则程序依然会崩溃,这个时候str指针依然是null。
百思不得其原因所在,还请兄弟们解惑
发表于 2006-1-8 12:07:27 | 显示全部楼层
我研究了一下不知道484这个意思
这个代码其实要做的是传地址
str的里面要放的是分配的100char的空间的地址,然后再可以strcpy拷贝进去字符串
*str是说明str里的内容是一个地址,我们现在要取这个地址里包括的内容。
str是str内存单位里的一个值,这个值只是一个地址。
getmemory(str)只是把str的值传过去
p拿到的是str的值(一个地址),然后在这个地址所指的内存空间放入动态分配的100个char的首地址。
这时候*str里还是空,所以程序崩溃。


第二个,它把str自己的地址传给子函数。p是指的str的地址,*p就是str里的内容,这个内容放进去的是动态分配的100个char的首地址。这个时候对str来说他里面的值是地址,所以strcpy可以复制了。


最后结论,我自己还有点搞。。。。
回复 支持 反对

使用道具 举报

发表于 2006-1-8 12:15:35 | 显示全部楼层
相信楼主看看《C专家编程》等书中有关函数调用是怎样以栈的方式来进行的,就会感到问题很简单了,我记得《C专家编程》里面好像有一幅形象的图来说明这个问题。
阐述起来太麻烦了,而且也不比书上讲的细,这里提提其核心思想是:
(1)不同的栈区域放置不同函数的局部变量
(2)在(1)这个栈模型基础上,所谓的传值调用和传指针调用是怎么回事(本质上都是将值从一个栈区域拷贝到另一个区域)
回复 支持 反对

使用道具 举报

发表于 2006-1-9 11:58:16 | 显示全部楼层
只要理解C语言的参数传递机制就好办了。
具体的搜索一下以前的贴子。
回复 支持 反对

使用道具 举报

发表于 2006-1-9 13:06:49 | 显示全部楼层
Post by sleepwalker
可是下面一个例子却是可以正确运行:
2,void getmemory(char **p)
     {
           *p = (char*)malloc(100);
      }
     void test(void)
     {
          char *str = NULL;
          getmemory(&str);
          strcpy(str, "hello);
          printf(str);
       }
我不明白的是两个例子中函数的形参都是指针,只是一个是指针,一个二重指针,为什么一个不可以传递动态内存,而另一个就可以呢?
另外,我发现,若在第二个版本的getmemory函数里面对p所指的内存区进行写操作,比如strcpy,则程序依然会崩溃,这个时候str指针依然是null。
百思不得其原因所在,还请兄弟们解惑


指出你的一个笔误: printf(str) 这样的参数会让printf 以为  str是格式字串。printf 由于可以接受可变参数,所以C实现里头不会检查其参数个数和参数类型,但会保证第一个实参为格式字串。

我下面的代码没发现你说的崩溃问题。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. void getmemory(char **p)
  5. {
  6.         *p = (char*)malloc(10);
  7.         printf("*p addr:%d\n",*p);
  8.         strcpy(*p,"world\0");
  9.         printf("*p content:%s\n",*p);

  10. }
  11. void test(void)
  12. {
  13.         char *str = NULL;
  14.         printf("str addr:%d\n", str);
  15.         getmemory(&str);
  16.         printf("str addr:%d\n", str);
  17.         strcpy(str, "hello\0");
  18.         printf("str content:%s\n",str);
  19.         free(str);
  20. }

  21. int main()
  22. {
  23.         test();
  24. }

复制代码
回复 支持 反对

使用道具 举报

发表于 2006-1-9 13:58:19 | 显示全部楼层
to  sleepwalker: 第二个没有问题,至少我的实验结果是这样。
to Lolita: 类似“hello”这样的字符串也是格式化字符串
回复 支持 反对

使用道具 举报

发表于 2006-1-9 14:06:33 | 显示全部楼层
Post by rickxbx
to Lolita: 类似“hello”这样的字符串也是格式化字符串

看来的确如此。
我换个shell以后才可以 printf("hello") 和 printf(str)了,原来会空白一片,估计是彩色prompt的缘故
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表