user-0 提问: 函数如何优雅的返回一个未知长度的字符串

回复:
user: user-0
content: 引用 23 楼 schlafenhamster 的回复:要改变 指针的 内容 请使用 双星 指针 （char **） int MyDllfunction(char * str_in) {     str_in = (char *)malloc(n);//n为动态大小     return n; } 是个 错误函数 ！ 额这个我知道，我随手敲了一个

user: user-1
content: 引用 11 楼 yiyefangzhou24 的回复:配对写的话貌似提供给客户的接口不是非常友好，各位是不是遇到类似问题的时候都配对写一个？ 配对是常规做法...... 大家都习惯了，就跟malloc要一个free配对一样，只要你的客户是个靠谱的程序员，他就不会吐槽这样接口。楼主不必在这方面钻太多牛角尖

user: user-2
content: 还不如使用临时文件简单粗暴。

user: user-3
content: 如果使用电脑早,肯定记得以前时不时弹出内存无法read,子类的错误.后来ms改用c#,这类问题就很少出现了.

user: user-3
content: 这本来就是c语言的老大难问题(直白的说就是没有什么太好的解决办法). c++11引入了智能指针,能部分解决这类忘记free导致内存泄漏的事情. 而java和c#为此几乎已经放弃手动管理指针了.

user: user-4
content: 引用 21 楼 Saleayas 的回复:让使用者传入缓冲区和缓冲区大小，返回时填写缓冲区，并返回实际的长度。 Windows API 很多都是这样的写法。 我觉得不应该让库自己来申请内存。  这是正解，其它都是不严谨的土办法，有时看起来很管用，实际上隐患和漏洞很多。。

user: user-5
content: 如 int MyDllfunction(char **str_in) {     char *tmp=(char *)malloc(10);//n为动态大小 	memset(tmp,0,10); 	strcpy(tmp,"123456789"); 	*str_in=tmp; 	OutputDebugString(*str_in); //     return 10; }

user: user-5
content: 要改变 指针的 内容 请使用 双星 指针 （char **） int MyDllfunction(char * str_in) {     str_in = (char *)malloc(n);//n为动态大小     return n; } 是个 错误函数 ！

user: user-2
content: 装逼优雅比不上简单粗暴 阳春白雪比不上下里巴人 满汉全席比不上街边小吃 个人意见

user: user-6
content: 让使用者传入缓冲区和缓冲区大小，返回时填写缓冲区，并返回实际的长度。 Windows API 很多都是这样的写法。 我觉得不应该让库自己来申请内存。

user: user-7
content: 这样一般不是返回值吧，基本上长度未知，肯定由调用者来申请这个空间，然后作为参数传入，得到想要的数据后，调用者在自己的作用域内释放内存

user: user-8
content: 就想看看怎样的才算优雅

user: user-9
content: 可以参照很多API的思路，函数需要外部提供一个缓冲区，如果缓冲区是NULL，函数返回这个缓冲区需要的大小，否则将字符串返回到这个缓冲区中，这样可以外部分配外部释放

user: user-10
content: 引用 10 楼 yiyefangzhou24 的回复:额，这其实还是需要调用者主动free，dll的malloc确实不能在主程序中free  dll内部申请的内存 ， 能不能在外部释放，取决于你的 dll  和 外部程序  链接的是不是同一个crt库， 以及是dll是动态链接还是静态链接 。  静态链接的同一个版本的crt的话， 外部释放是没有问题的，否则是不能由外部 释放 dll内部申请的内存的。  所以保险起见，一般都是dll内部申请的内存， 就是dll自己释放，dll提供释放接口给外部调用

user: user-11
content: 引用 9 楼 yiyefangzhou24 的回复:[quote=引用 8 楼 cfjtaishan 的回复:] [quote=引用 5 楼 yiyefangzhou24 的回复:] [quote=引用 3 楼 cfjtaishan 的回复:] 那么可以谁用谁申请，就像strcpy那样，要返回一个字符串，调用函数的人要传入一个有效的内存空间，这样不论调用者是malloc还是定义数组还是全局变量都不关心。 函数只关心自己的功能，符合模块设计的思路 关键是调用函数的人不清楚函数会返回多长的字符串啊，比如函数实现的是winsock 的recv的分包的拼接，不知道会拼几个包，有多长[/quote] 那么可以通过其他方式得到，比如传入两个参数，一个是首地址，一个是长度。就像recv一样，根据长度拷贝字节到缓存里，若一次完全得到，则返回一个值，如果需要两次或者更多次，可以根据返回值的不同来调节。[/quote] 有利用缓存输入输出的例子吗？recv的缓存应该不是用户态下实现的吧？[/quote] 不是，我的意思是可以借鉴一下； recv每次读取时，若传入的缓存长度是10，那么读到的长度是5，则说明完全读到了，如果是返回10，则可能读完全了，数据可能大于10，也可能正好是10（字节）

user: user-0
content: 配对写的话貌似提供给客户的接口不是非常友好，各位是不是遇到类似问题的时候都配对写一个？

user: user-0
content: 引用 6 楼 zilaishuichina 的回复:[quote=引用 4 楼 yiyefangzhou24 的回复:]   [quote=引用 1 楼 zilaishuichina 的回复:] 如果是c的话，   对方调用你的 char* MallocString(int len) 获得一个字符串， 就应该是对方调用你的 void FreeString(char* str); 去释放字符串， 谁申请谁释放，反过来，谁提供申请接口，就谁提供释放接口  c++就直接返回string 实际情况是写一个纯c的dll，对外提供一个返回字符串的函数，但是调用者不清楚这个函数要返回多长的字符串 举个例子  //dll空间 int MyDllfunction(char * str_in) {     str_in = (char *)malloc(n);//n为动态大小     return n; } //主程序空间 char * str=NULL; if(MyDllfunction(str)) { ... }  这样就必须调用者在主程序空间中free，不够统一，提供的接口也不够友好 [/quote]  这不是一样的么， 就是你dll里面 需要再提供一个 void MyDllFreefunction(char * str_in) ，提供给对方调用，具体的释放逻辑是在dll里面释放的，  char * str=NULL; if(MyDllfunction(str)) {     //...      MyDllFreefunction(str); }[/quote] 额，这其实还是需要调用者主动free，dll的malloc确实不能在主程序中free

user: user-0
content: 引用 8 楼 cfjtaishan 的回复:[quote=引用 5 楼 yiyefangzhou24 的回复:] [quote=引用 3 楼 cfjtaishan 的回复:] 那么可以谁用谁申请，就像strcpy那样，要返回一个字符串，调用函数的人要传入一个有效的内存空间，这样不论调用者是malloc还是定义数组还是全局变量都不关心。 函数只关心自己的功能，符合模块设计的思路 关键是调用函数的人不清楚函数会返回多长的字符串啊，比如函数实现的是winsock 的recv的分包的拼接，不知道会拼几个包，有多长[/quote] 那么可以通过其他方式得到，比如传入两个参数，一个是首地址，一个是长度。就像recv一样，根据长度拷贝字节到缓存里，若一次完全得到，则返回一个值，如果需要两次或者更多次，可以根据返回值的不同来调节。[/quote] 有利用缓存输入输出的例子吗？recv的缓存应该不是用户态下实现的吧？

user: user-11
content: 引用 5 楼 yiyefangzhou24 的回复:[quote=引用 3 楼 cfjtaishan 的回复:] 那么可以谁用谁申请，就像strcpy那样，要返回一个字符串，调用函数的人要传入一个有效的内存空间，这样不论调用者是malloc还是定义数组还是全局变量都不关心。 函数只关心自己的功能，符合模块设计的思路 关键是调用函数的人不清楚函数会返回多长的字符串啊，比如函数实现的是winsock 的recv的分包的拼接，不知道会拼几个包，有多长[/quote] 那么可以通过其他方式得到，比如传入两个参数，一个是首地址，一个是长度。就像recv一样，根据长度拷贝字节到缓存里，若一次完全得到，则返回一个值，如果需要两次或者更多次，可以根据返回值的不同来调节。

user: user-12
content: 再写个释放函数配对