4135|11

7815

帖子

56

TA的资源

裸片初长成(中级)

楼主
 

【靠谱例程联盟】关于malloc/realloc在函数间的内存传递问题 20131216 [复制链接]

在 20131206 的 记录里   (这份记录在qq群论坛里,鉴于经常打不开,所以直接copy到这里)

      c里,数组,特别是字符串,在处理各种添加结束符和处理时,总是十分麻烦,当然c++就省了这些,只要你听从c++ primer的建议,用vector+string取代所有C样式的使用数组。当然,c还是要用的,数组还是要用的,那么……让我们来写一套类似于c++ string vector的工具给它使用吧!

-------------------------------------------------------------------------------------------------------------

     于是我考虑,先以一个 连接字符串 的函数入手,假设在c里,我们经常需要自行完成包括内存分配在内的很多细节,而在c++的string类里,我们是不需要考虑这么多的,可以直接就这么 catch上去,这是非常爽的。
     
     这里头其实只涉及了两个技术点:
     1.动态分配内存
        具体地说,我们的目标是,传入函数的只需要一个指针,而无需考虑它的空间分配问题。我们只关心字符串的操作效果;
     2.内存泄漏的防止
        因为我们打算把内存分配的工作留在函数里完成,因此(当然,也是在后来的操作过程中实际遇到,才知道需要考虑的)
        因此为了防止内存泄漏,我们必须考虑如何在不同的函数释放内存。

     目前的状况,内存泄漏的问题还没解决,而连接已经完成了。
     整理一下,沙发贴上代码。
此帖出自编程基础论坛

最新回复

if(*dest == NULL) {strcpy(*dest,buff);return -1;} // 在分配出错时,确保原数据可以恢复; 我觉得你这个有问题啊,buff = *dest;  的情况下 只是相当与把指针头保存下来,所以在strcpy(*dest,buff)  的意义更接近 *dest ++= *dest++ 是一样,把指针头扔回给*dest =buff 还好一点,假如是 buff=malloc (*dest) 那是真的把整数据链给保存下来了。 另外你说free(buff);  错误? [ 本帖最后由 虚V界 于 2013-12-17 13:41 编辑 ]  详情 回复 发表于 2013-12-17 13:36
点赞 关注
 

回复
举报

1100

帖子

3

TA的资源

五彩晶圆(初级)

沙发
 
呵呵,顶你个肺
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

板凳
 

尚未妥善释放内存的 StringCatch(v0.1)——不能在函数释放来自主调方的内存?

  1. int StringCatch(char **dest,char *sub)
  2. {
  3.     char *buff = NULL;
  4.        
  5.     if(dest == NULL || sub == NULL) return -1;

  6.         buff = *dest;
  7.          
  8.         *dest = (char *)malloc(sizeof(char) * (strlen(buff) + strlen(sub) + 1) );

  9.         if(*dest == NULL) {strcpy(*dest,buff);return -1;} // 在分配出错时,确保原数据可以恢复;
  10.        
  11.     strcpy(*dest,buff);
  12.         strcat(*dest,sub);
  13.         printf("=== in function\nwe get\n %s\n",*dest);      // 输出测试信息
  14.         //free(buff); buff = NULL;
  15.        
  16.         return 0;
  17. }
复制代码
这个函数的实现方法,最基本的思想是。
在函数内部用一个指针记录原字符串的地址;
然后对该字符串指针*dest(来自主调函数)重新分配内存。
如果发生错误,我仍然可以取回原数据,确保函数的错误操作不会破坏原数据;
其次,一旦成功操作,因为我在重新分配以前故意不释放它,所以我希望在成功连接后,通过释放buff记录的地址,去释放原内存,以避免这部分内存泄漏。

但是我发现这样操作会报错。
暂时想不通为什么。

然后我试过做一个很单纯的测试。
就是对函数传入一个主调方的内存,让函数释放,同样会出错。
所以,这个地方是关键,关键在于,
它似乎在暗示我:不能在函数释放来自主调方的内存?
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

4
 

回复 沙发gaoyang9992006 的帖子

光顶是不行的啊
说好了联盟,得帮忙啊。

帮忙解决程序问题,还希望你们多多提供有用,经过实际验证的例程啊。

哪怕只是一个十几行的代码片段,只要是经过确实验证的,都是很有用的啊!
此帖出自编程基础论坛
 
 
 

回复

6423

帖子

17

TA的资源

版主

5
 
我看这个靠谱
此帖出自编程基础论坛
 
 
 

回复

1100

帖子

3

TA的资源

五彩晶圆(初级)

6
 
en ,hao,OK
此帖出自编程基础论坛
 
 
 

回复

381

帖子

0

TA的资源

纯净的硅(高级)

7
 

回复 板凳辛昕 的帖子

if(*dest == NULL) {strcpy(*dest,buff);return -1;} // 在分配出错时,确保原数据可以恢复;
我觉得你这个有问题啊,buff = *dest;  的情况下 只是相当与把指针头保存下来,所以在strcpy(*dest,buff)  的意义更接近 *dest ++= *dest++ 是一样,把指针头扔回给*dest =buff 还好一点,假如是 buff=malloc (*dest) 那是真的把整数据链给保存下来了。

另外你说free(buff);  错误?

[ 本帖最后由 虚V界 于 2013-12-17 13:41 编辑 ]
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

8
 
首先解释一下 关于 释放掉原来的内存出错的问题.
C与指针这本书里提到了原因
因为free函数传入的指针(内存)只能是用malloc,realloc calloc之类的函数动态分配出来的内存,否则就会造成程序终止或者晚些时候终止。

所以这提醒我必须改变思路,来改变内存。
同样的道理,realloc也是,传递给他的内存必须是malloc,calloc动态分配的内存;
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

9
 

回复 7楼虚V界 的帖子

这个地方我看不太懂你的意思。
你的意思是 要取回原内存快
就必须用strcpy或者逐个逐个赋值回去?

而不能光光传递指针?

非也,虽然我暂时想不出办法模拟分配失败或者其他方式证明这个结论。
但从原理上分析,我确信这是没有问题的。
因为这两个地址都是带着一块有效的内存块,这个内存块也没有被释放,因此只传递指针携带的地址,是没有问题。

fine,我来一段代码验证和测试。
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

10
 

回复 7楼虚V界 的帖子

  1. void Test_TransBuffViaPoint(void)
  2. {
  3.         char *buff = "Holding.\n";
  4.         char *pointerRecord = buff;
  5.         
  6.         printf("previous,we have buff with string\n %s\n",buff);
  7.         buff = (char *)malloc(100); //已经重新分配了;
  8.         if(buff == NULL) printf("allocate failed!");
  9.         else             printf("now,we malloc the buff again,we get a new addr \n%p\n",buff);
  10.         
  11.         printf("for simulate the malloc failed case,\nI will set pointer to NULL.\n");
  12.         buff = NULL;
  13.         if(buff == NULL) printf("now,buff had been set to NULL");
  14.         else             printf("Jesus!This must be impossible to happen!\n");
  15.         
  16.         printf("now,we pass the record back to buff");
  17.         buff = pointerRecord;
  18.         printf("so...now let's see what we get from buff\n%s\n",buff);        
  19. }
复制代码
运行结果:


[ 本帖最后由 辛昕 于 2013-12-18 02:24 编辑 ]
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

11
 

解决方案 20131218

解决方案 20131218
      上述所言,麻烦在于 malloc/realloc/calloc 和 free函数,都只能操作 动态分配的内存,亦即是  栈上的内存。

      考虑一个重要问题。
      我们当然最希望这个函数可以非常广泛的使用,不管用户传入的内存 是 来自 定义变量(堆上),甚至是如我的例程里随手写的已给 常量区 的 内存。然而,反复考虑都没有找到更好的方法。如果要自己去考虑重新查看 堆 和 栈 这些不同内存区的操作,那实在太麻烦,而且可能不适用各类机型(单片机,PC机)。

      因此,考虑第二种方案,模仿c++的string类型,虽然C没有类,但一样可以通过结构体封装和变通的方法实现。
   如此内存的创建,销毁,重分配完全控制在实现方案内部,如此,就可以不担心 free掉 非栈上 的内存而出现错误了


      另外就是,我刚重新测试了一下,在iar下,在stm8s下,是可以动态分配的。只是,也许跟栈的大小设置有关,我一开始试图分配1000bytes时会出错,但如果只分配100bytes则不出错。

[ 本帖最后由 辛昕 于 2013-12-18 18:39 编辑 ]
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

12
 

其实,当时,我无非是想实现c++式的string或者vector

但是,这其实是很难的,我开始想一个问题。

如果我在一个库里实现的时候也是用C++语法,我如何确认使用最基础的C++部分,是否会更加好呢?

此帖出自编程基础论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表