CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C语言

关于A函数申请内存,B函数释放大家有什么好的解决方法

楼主CodeMagic(ErrorDetector)2006-05-28 11:18:35 在 C/C++ / C语言 提问

大家编程时,难免会遇到这种问题,但遵循的原则一般都是谁申请   谁释放。  
   
  假设函数B需要从文件中读到一写数据,为了模块化的目的,我可能把操作文件数据的函数都独立出来,使函数B看不到具体的文件结构细节。于是函数B为了得到数据,必须访问上述操纵数据的Api(假设为函数A)。  
   
  因为B不知道数据的具体大小,所以所需要malloc的空间也不知道多大,因此把申请空间的工作交给A来做了,最后由B来释放A申请的内存。这也就是上面提出的A申请,B释放的缘由,但好像大家不喜欢这样的编程方式,一般都遵循谁申请   谁释放的原则。  
   
  请问大家对此有何解决办法?  
   
  我现在想到一种解决方法是:在B中传递一个二维指针,即地址的地址,这样的话A把申请的地址放到B中,但仍避免不了这个问题。  
  问题点数:50、回复次数:43Top

1 楼jixingzhong(瞌睡虫·星辰)回复于 2006-05-28 11:28:05 得分 2

一般都是   谁申请谁释放,  
  但是这个也不是绝对的   ......  
   
  在   B   中释放也完全可以,  
  只不过需要注意很多问题,  
  存在一些潜在的状况而已   ....Top

2 楼CodeMagic(ErrorDetector)回复于 2006-05-28 11:39:15 得分 0

但是如果由B申请,B释放的话,因为B不知道提前malloc空间的大小,需要A那边另外做一个接口,获得申请的大小,然后B再根据这个大小来申请需要的空间。  
   
  至于这个接口是不是需要单独做成一个函数,还是由函数A来承担,那只是实现上的事情了。  
   
  是不是只有这么一种解决方案了?Top

3 楼samoonm()回复于 2006-05-28 12:38:14 得分 1

在数据里面记录自身的大小行不行?Top

4 楼CodeMagic(ErrorDetector)回复于 2006-05-28 14:37:28 得分 0

那也可以,那就是让B提前知道这个大小了Top

5 楼vincentcsdn(DemonPumpkin)回复于 2006-05-28 15:49:06 得分 1

可以使用智能指针。  
  例如CString   ,String   auto_ptr   之类的  
   
  也可以根据需要自己订制.Top

6 楼CodeMagic(ErrorDetector)回复于 2006-05-28 16:05:06 得分 0

老大,c语言支持么?Top

7 楼Kenmark(fenix)回复于 2006-05-28 17:44:30 得分 1

不太好地习惯,容易造成内存归属不明确,应该是谁非配谁管理,OO就是要实现这种功能,类自己地事情自己管,大的工程如果是用A分配B释放地方法会让人头疼地!Top

8 楼CodeMagic(ErrorDetector)回复于 2006-05-28 19:23:58 得分 0

那有好的解决方法么,除了我给的这种?  
   
  但是如果由B申请,B释放的话,因为B不知道提前malloc空间的大小,需要A那边另外做一个接口,获得申请的大小,然后B再根据这个大小来申请需要的空间。  
   
  至于这个接口是不是需要单独做成一个函数,还是由函数A来承担,那只是实现上的事情了。Top

9 楼crazy_lazy_pig(疯狂懒猪)回复于 2006-05-28 20:11:10 得分 2

为什么一定要由A来申请呢?   我认为这即会出现麻烦,   也不易读,   更不易维护,   至于运行质量不是很好评价了.    
   
  我认为可以让A仅返回文件大小(即malloc需要的大小),   然后在B中调用A,   进而申请空间.  
   
  还有,   你的问题我在逻辑上有点想不通:   B用来获取文件数据,   A用来处理数据,   但是B不知道申请多大的空间,   为了安全的读数据必须由A的处理数据功能来申请空间,   可是A自己得不到数据,   必须由B来获取数据.   这样B为了读数据需要等待A的结果,   A给出结果需要B的数据,   这不是死锁了吗?Top

10 楼CodeMagic(ErrorDetector)回复于 2006-05-28 21:32:42 得分 0

是这样的,我现在做嵌入式开发,上层界面那一部分是不应该涉及到底层数据的处理逻辑的(例如直接打开文件,移动文件指针来读取数据。这样做会导致代码的维护性差,一旦底层文件的结构发生变化,就得改上层的处理逻辑),所以我把数据的处理单独做一些函数来供界面使用。这里的函数B处于界面那一层,函数A处于数据处理那一层了。Top

11 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-05-28 22:01:35 得分 2

Implement   IUnknown  
  marshal   calls   between   threadsTop

12 楼CodeMagic(ErrorDetector)回复于 2006-05-28 22:17:53 得分 0

One   point   i   must   mention,   the   language   i   use   is   C,   not   C++  
  And   dont   interven   the   concept   of   threadTop

13 楼cattlenzq(吃狼的豆腐(不要给分了,散起来真麻烦!))回复于 2006-05-28 22:32:03 得分 1

实在不行就在析构函数解决吧Top

14 楼crazy_lazy_pig(疯狂懒猪)回复于 2006-05-28 23:15:38 得分 2

真搞不懂你的设计思路是什么,   我认为还是设计理念上有问题,   逻辑上还是讲不通.    
  界面无非就是人机对话界面,   它无疑是要处理输入和输出,   而底层功能模块是作数据处理.     然而,   输入与输出也是与数据结构紧密相连的,   这就牵扯到界面模块和底层模块如何划分的问题了.   我没用C写过类似的程序,   但是C++的GUI编程思想是这样的:   界面(GUI)是数据无关的,   即窗口,菜单,对话框等(有没有数据,   有什么样的数据,   我的窗口,菜单等东西都可以那么样画),   而数据相关的内容(包括文件存贮)都放到了底层(也就是说没有GUI,   我一样可以存取文件),   界面模块是通过调用底层模块来实现功能的.  
   
  所以我认为,   你的文件读取函数肯定要放到底层去的,   而界面仅仅是调用这个函数而已,   这样,   无论你怎么改数据处理函数,   界面都可以不变的.Top

15 楼CodeMagic(ErrorDetector)回复于 2006-05-28 23:53:32 得分 0

是呀,现在就是这样设计的,界面不知道底层数据的组织,只需要调用相应的函数而已,关键在于内存的分配上。Top

16 楼happytang(一只叫苏格拉底的猪)回复于 2006-05-29 00:05:09 得分 1

定义一个全局的结构,比如消息队列,通过传递消息来申请和释放  
  这在嵌入式系统中很容易实现Top

17 楼wxfy1977(我心飞扬)回复于 2006-05-29 09:35:25 得分 1

在A中返回分配的大小,传回分配的地址Top

18 楼magicianxcs()回复于 2006-05-29 10:17:19 得分 1

可以参考windows   API   函数的设计。Top

19 楼BluntBlade(信仰迷离·重构之道,在于Redo/Undo之间)回复于 2006-05-29 10:25:19 得分 2

对待处女,谁污染,谁治理;  
  对待内存,谁分配,谁释放。  
   
  如果感觉不对劲,请重新设计你的软件。Top

20 楼Muf(沐枫)回复于 2006-05-29 11:04:45 得分 2

关于文件处理,现有的许多API都已经是很成熟了。  
   
  比如A是用于读取文件数据的,B是用于处理数据的。  
  这里:  
  1.   A是如何读取数据呢?全部读还是部份读,将来如果想要读任意大小怎么办?  
  2.   B是如何处理数据呢?全部处理还是部份处理,将来如果只想处理其中的部份数据怎么办?  
   
  所以,关键是A能不能提供一个灵活的接口。  
  可以参考fread函数:由B提供缓冲区,并告诉A,缓冲区的大小,由A来读取相应大小的数据。  
  这样,问题不就结了。Top

21 楼CodeMagic(ErrorDetector)回复于 2006-05-29 12:17:12 得分 0

是这样的,如果让A来申请内存,那么A可以对malloc的结果进行统一判断,如果让B来做这件事情,那么可能有若干个类似于B的函数,都需要调用A,那么对malloc结果的判断,有多少调用就得的重复多少次判断。Top

22 楼Muf(沐枫)回复于 2006-05-29 13:39:26 得分 2

是的,这才是应该 做的。  
  因为,对malloc的结果判断,有时候是必须的,有时候不是必须的。而且,有时候用malloc分配比较好,有时候用数组比较好,有时候用系统分配(如GlobalAlloc)。让B去做这些事,可以保证A是最好的。Top

23 楼cutenoob(cute )回复于 2006-05-29 15:56:58 得分 2

我现在想到一种解决方法是:在B中传递一个二维指针,即地址的地址,这样的话A把申请的地址放到B中,但仍避免不了这个问题。  
  -------------------  
   
  请问lz   你这种方法的缺陷又在哪里?我也想到这种方法了....  
  Top

24 楼CodeMagic(ErrorDetector)回复于 2006-05-29 16:28:47 得分 0

容易导致内存泄露,因为你需要关心从别的函数得来的指针是否需要自己释放Top

25 楼wgjmail(笑面佛)回复于 2006-05-29 18:11:28 得分 1

传个文件长度的变量不就行了.Top

26 楼FreeFice(庄鱼)回复于 2006-05-29 18:25:31 得分 2

符合下述规则:  
  class   A;  
  A   *make(A   &a)//()  
  {  
        return   new   A(a);//new   A();  
  }  
   
  void   Free(A*   &a)  
  {  
        if(a){  
              delete   a;  
              a=0;}  
  }  
  也可以使用下述函数获取指针:  
  int   NewOne(A   **a){  
        if(*a)  
              return   ERROR;  
        try{  
              *a   =   new   A();}  
        catch(...){  
              return   FAIL;}  
        return   OK;  
  }Top

27 楼Wolf0403(废人:独活十年~心如刀割)回复于 2006-05-29 19:53:14 得分 1

我觉得   A   分配   B   释放未必就是洪水猛兽。。只要能通过某种方法使   A   和   B   对需要释放的资源达成共识就可以了……Top

28 楼Wolf0403(废人:独活十年~心如刀割)回复于 2006-05-29 19:56:41 得分 1

另外,底层和   GUI   之间共享数据,我不明白为什么不能由底层来释放资源。。Top

29 楼crazy_lazy_pig(疯狂懒猪)回复于 2006-05-29 22:53:55 得分 2

lz   的意思我终于看明白了,   这里面的问题确实非常的多,   这就是面向对象思想出现的原因,   也最终相对于C语言出现了C++.   你的问题在C++里似乎得到了比较好的解决,   下面是我作的程序的大体思路:  
   
  我的程序主要是三个类相互配合协同完成各功能command类实现内存的申请与施放,   document实现数据的各种处理,   view负责把document的内容显示的屏幕上,   并调用command的公有函数实现对document数据的增减.   这里view属于界面部分,   另外两个类属于底层.   这里面view不带有数据,   仅仅是通过调用document里的函数来显示数据(document的变化毫不影响view),   document的有效数据都是指针,   指向command申请出来的对象.   command带有有效的成员变量,   在构造函数里通过new来申请空间,   析构函数里施放空间,   并由view的桥梁作用来充实(减少)document的数据.   下面的关键问题就是保证command对象的生存时间比document内的数据生存时间要长,   这很容易实现,   只要在你的程序里让command的地位比document更底层就可以了.   其实现在的GUI库都已经充分考虑到了这些问题,   它会自动给你处理好的.  
  Top

30 楼crazy_lazy_pig(疯狂懒猪)回复于 2006-05-29 23:03:00 得分 1

再稍微解释一下command比document更底层的意义:  
  在我的程序里,   command完全负责document的数据的增减,   在command内部有标志变量标明当前状态是给document增了数据还是减了数据(其实真正的实现还要更复杂,甚至于标明了增减的数据类型以及状态),   只有当状态是减的时候(这时document已不含有该command的数据指针了),   command对象才有消亡的可能(这当然是有某种机制可以控制的).Top

31 楼crazy_lazy_pig(疯狂懒猪)回复于 2006-05-29 23:04:54 得分 1

呵呵,   胡说一通,   不知道这种思想能不能被你转化到C程序中去.Top

32 楼HeShe(呵呵)回复于 2006-05-30 10:52:26 得分 2

我觉得在C中这其实也是一种比较普遍的情况。一般将数据本应该是一个实体,对其封装,统一管理。  
  typedef   _HANDLE  
  {  
        char*pData;  
        int   iDataLen;  
  }*DATAHANDLE;  
  DATAHANDLE   A_CreateData()  
  {  
      DATAHANDLE   p=malloc(struct   _HANDLE);  
  }  
  ClosHandle(DATAHANDLE   handle)  
  {  
      free(handle->pData);  
      free(handle);  
  }  
  B(DATAHANDLE   handle)  
  {  
        CloseHandle(handle);  
  }  
  个人偏好在B外面CloseHandle(handle):  
  mail()  
  {  
      handle=A_CreateData();  
      B(handle);  
      CloseHandle(handle);  
  }Top

33 楼redsocks()回复于 2006-05-30 11:43:04 得分 1

HeShe(呵呵)   的做法比较好!支持!Top

34 楼iambic()回复于 2006-05-30 11:58:11 得分 1

比较简单的方法就是细分函数职能,统一函数名。把内存的申请释放统一使用newType(),deleteType(T*   p),可以在其中增加内存管理(比如记录申请并未归还的内存)。这是一种风格,不是保障机制。但这种风格往往能提醒你少犯错误。Top

35 楼studiovc()回复于 2006-05-30 18:06:48 得分 2

b();  
  getBsize();  
  a()  
  {  
   
  long   lbsize;  
  lbsize=getBsize();  
  malloc();  
  ....  
  free();  
  }  
   
  Top

36 楼tjuzhangrui()回复于 2006-07-05 15:28:49 得分 2

关于文件处理,现有的许多API都已经是很成熟了。  
   
  比如A是用于读取文件数据的,B是用于处理数据的。  
  这里:  
  1.   A是如何读取数据呢?全部读还是部份读,将来如果想要读任意大小怎么办?  
  2.   B是如何处理数据呢?全部处理还是部份处理,将来如果只想处理其中的部份数据怎么办?  
   
  所以,关键是A能不能提供一个灵活的接口。  
  可以参考fread函数:由B提供缓冲区,并告诉A,缓冲区的大小,由A来读取相应大小的数据。  
  这样,问题不就结了。  
   
  --------------------------------------------------  
  恕我直言,我觉得为了遵循“谁申请谁释放”的原则这么写函数是一个比较SB的做法,因为有时候你不知道要开多大的内存。但是如果遵循这个原则我又想不出更好的办法,也想不出这么做的好处在哪,所以只好A申请,B释放。谁能为我解惑啊。Top

37 楼tjuzhangrui()回复于 2006-07-05 15:34:52 得分 2

crazy_lazy_pig(疯狂懒猪)   (   )   信誉:100     2006-5-29   22:53:56     得分:   0      
     
     
         
  lz   的意思我终于看明白了,   这里面的问题确实非常的多,   这就是面向对象思想出现的原因,   也最终相对于C语言出现了C++.   你的问题在C++里似乎得到了比较好的解决,   下面是我作的程序的大体思路:  
   
  我的程序主要是三个类相互配合协同完成各功能command类实现内存的申请与施放,   document实现数据的各种处理,   view负责把document的内容显示的屏幕上,   并调用command的公有函数实现对document数据的增减.   这里view属于界面部分,   另外两个类属于底层.   这里面view不带有数据,   仅仅是通过调用document里的函数来显示数据(document的变化毫不影响view),   document的有效数据都是指针,   指向command申请出来的对象.   command带有有效的成员变量,   在构造函数里通过new来申请空间,   析构函数里施放空间,   并由view的桥梁作用来充实(减少)document的数据.   下面的关键问题就是保证command对象的生存时间比document内的数据生存时间要长,   这很容易实现,   只要在你的程序里让command的地位比document更底层就可以了.   其实现在的GUI库都已经充分考虑到了这些问题,   它会自动给你处理好的.  
  ---------------------------------------------------------------------------  
  有一个问题是,“command带有有效的成员变量,   在构造函数里通过new来申请空间”,构造函数怎么知道申请多大的空间?谢谢!Top

38 楼tailzhou(尾巴)回复于 2006-07-05 16:05:52 得分 1

好多api函数好象都是第一次调用获取需要的空间的大小;  
  分配好空间后;  
  使用分配的地址作为参数再次调用api函数.  
  Top

39 楼crazy_lazy_pig(疯狂懒猪)回复于 2006-07-05 16:12:03 得分 2

恩,这是个问题。  
   
  我的程序只是一个对象一个对象的申请空间,应该是view(或者是document)知道需要多少对象,需要几个就生成几个command,不过这样讲似乎command就等价于数据了。但是我的command对象都是在栈空间里的,它是由系统决定存亡的,不用我操心,我所做的是把需要我操心的数据封装进了command类内。但是这似乎又有了问题,既系统把command对象析构掉时,是否还会有其他对象需要用到析构掉的数据?唉,实在是晕啊,我也不知道答案了。但是我从来还没出过问题,想必GUI库的document/view架构已经充分为我们考虑到了这些问题,我没好好研究过,研究研究这个机制应该会找到答案吧。Top

40 楼cc203203(为了过日子!)回复于 2006-07-26 09:54:30 得分 1

路过~~Top

41 楼SammyLan((基础决定你能走多远)--英语菜才是真的菜)回复于 2006-07-26 10:08:11 得分 2

A函数申请内存,B函数释放内存.....  
   
  为什么这都有那么多异议  
  在DLL编程中这是很常用的方法:在DLL中分配的内存必须由在DLL里面释放,所以提供一个分配内存的函数,必须要同时提供一个释放内存的函数.  
  看一下那么多系统函数就知道了,像GlobalAlloc(),HGLOBAL   GlobalFree(),etc............  
   
   
  在C中不直接支持面向对象  
  A函数申请内存,B函数释放内存正是面向对象思想的体现Top

42 楼SammyLan((基础决定你能走多远)--英语菜才是真的菜)回复于 2006-07-26 10:52:34 得分 2

...............这里的函数B处于界面那一层,函数A处于数据处理那一层了。  
   
  为什么函数B要放在界面一层,分配和释放的话函数要放在同一层,老大(=_=)  
  要是在模块化编程中,你将A封装在一个DLL,B却在另一模块,麻烦就大了Top

43 楼CodeMagic(ErrorDetector)回复于 2006-11-30 21:52:13 得分 0

不好意思,分不多,就这样吧。Top

相关问题

关键词

得分解答快速导航

  • 帖主:CodeMagic
  • jixingzhong
  • samoonm
  • vincentcsdn
  • Kenmark
  • crazy_lazy_pig
  • jiangsheng
  • cattlenzq
  • crazy_lazy_pig
  • happytang
  • wxfy1977
  • magicianxcs
  • BluntBlade
  • Muf
  • Muf
  • cutenoob
  • wgjmail
  • FreeFice
  • Wolf0403
  • Wolf0403
  • crazy_lazy_pig
  • crazy_lazy_pig
  • crazy_lazy_pig
  • HeShe
  • redsocks
  • iambic
  • studiovc
  • tjuzhangrui
  • tjuzhangrui
  • tailzhou
  • crazy_lazy_pig
  • cc203203
  • SammyLan
  • SammyLan

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo