方法在传递 [] 数组而不是来自 malloc 的内存时有效
Posted
技术标签:
【中文标题】方法在传递 [] 数组而不是来自 malloc 的内存时有效【英文标题】:Method works when passed [] array but not memory from malloc 【发布时间】:2017-04-18 08:53:51 【问题描述】:如果没有完整的代码,这个问题可能没有意义,但我会尽力解释它。作为背景知识,代码是来自 GitHub 上的 OpenThread 项目的 sn-p,但我相信标准的 c/c++ 原则仍然适用于此。
代码的目的是将一段数据(在本例中为字符串)附加到 OpenThread (ot) 消息上。作为参数,它需要一个 otMessage、一个缓冲区(带有数据)和要复制到 otMessage 中的缓冲区的长度。我不太确定otMessageAppend
是如何工作的,而且完全有可能错误在于它读取缓冲区的方式,如果是这种情况,则无能为力。
以下 c++ 代码是起点:
char command[] = "abcdef";
SuccessOrExit(error = otMessageAppend(message, &command, (uint16_t)strlen(command)*sizeof(char)));
在另一端收到消息时,我收到abcdef
当将abcdef
传递为argv[4]
时,此代码完美运行:
char command[strlen(argv[4])+1];//+1 for the null terminator
strcpy(command, argv[4]);
SuccessOrExit(error = otMessageAppend(message, &command, (uint16_t)strlen(command)*sizeof(char)));
但是尝试使用malloc
分配内存会导致垃圾从另一端流出(正确的字节数但不是正确的数据):
char *command;
command = (char *) malloc(strlen(argv[4])+1);
strcpy(command, argv[4]);
SuccessOrExit(error = otMessageAppend(message, &command, (uint16_t)strlen(command)*sizeof(char)));
我对此有几个问题:
-
使用
char array[size]
声明内存有什么问题吗?据我了解,区别在于使用[]
将在堆栈中分配内存,而malloc
在堆中分配内存。
如果我应该使用malloc
,我如何确保正确的内存将“附加到消息中”而不仅仅是垃圾
如果知道otAppendMessage
的工作原理很重要,我可以挖掘源代码并找到它。
【问题讨论】:
当command
是指针时,&command
具有不同的含义。你得到一个指向指针的指针,而不是指向字符串的指针。
您是在编程 C 还是 C++?它们是不同的语言,并且行为确实不同。考虑到您使用variable-length arrays 和malloc
,我假设您实际上是用C 编程的(在这种情况下,您应该阅读this discussion about casting the result of malloc
)?
如果是 c++,那为什么不用new
而不是malloc
?为什么不用std::string
而不是char*
?
编译时启用警告!并理解警告。
无论哪种方式,在不知道 otMessageAppend
的确切声明(Minimal, Complete, and Verifiable Example 会有所帮助)的情况下,您可能希望在构建时启用更多警告。对真正的数组(不是指针)使用 address-of 运算符通常是不会做的,如果参数不匹配,您会收到有关它的警告(或 C++ 中的错误)。
【参考方案1】:
将&command
替换为command
。
两个 sn-ps 都不好,但是第一个恰好起作用,因为数组的地址与其第一个元素的地址相同,并且如果参数的类型为 void*
,则两个表达式都会导致相同的转换参数。在第二个 sn-p 中,指针的地址肯定不等于指针的值(因为 malloc 的无别名保证)。
【讨论】:
如果 sn-ps 不好,我可以做些什么来改进它们,malloc
这样做有什么好处
@CampbellWray:你可以做些什么来改进它们,就像答案所说的那样,用command
替换&command
。使用自动内存还是动态内存取决于您更大的设计要求(字符串大小、寿命);您需要自己做出决定。
@CampbellWray 您需要在两个版本中删除&
。
感谢@AnttiHaapala 和Kerrek,我是在别人的代码之上构建的,所以我在很大程度上遵循他们所拥有的,因此&
。
@CampbellWray:我应该说,从洞察力和深思熟虑的角度进行编程可能比通过模式匹配、语法猜测和遵循食谱更有效。这个主题很复杂,通过拼凑不透明的构建块,你不太可能走得很远。以上是关于方法在传递 [] 数组而不是来自 malloc 的内存时有效的主要内容,如果未能解决你的问题,请参考以下文章
在 Matlab 中使用 Globals 而不是传递大型数组