【问题标题】:Using strncat method on arduino outputs an erroneous value在 arduino 上使用 strncat 方法输出错误值
【发布时间】:2014-08-30 06:42:22
【问题描述】:

我需要使用 GSM 模块解码 GPS 信号并将其发送到远程服务器。我分别生成纬度和经度值并连接到char 数组中。所以我可以轻松地将char* 传递给GSM 模块串行write() 方法。但是那些连接的字符串包含错误的值。我检查了解码后的值,它们有实数,但这只有在我将它连接到我的 char 数组时才会发生。我在 Arduino Uno 上运行此代码:

void loop()
{
  char data[128];
  data[0]='\0';
  initialize();

  strncat(data,getLat(),10);
  strncat(data," ",2);
  strncat(data,getLon(),10);

  Serial.write(data);
  Serial.println();

}

char* getLat(){
  char buffer[10];
  dtostrf(flat, 3, 6, buffer);
  Serial.write(buffer);
  Serial.print(" ");
  return buffer;
}

输出如下所示:前两列是调用 getLat() 方法时刚刚打印的值(转换中没有错误),后两列是连接的部分。

 6.929772 79.947296    Àb 79.947296
 6.929772 79.947296    6.929772 79.947296
 6.929772 79.947296    6.929772 79.947296
 6.929772 79.947296    6.929772 79.947296
 6.929772 79.947296    6.929772 79tdt
 6.929772 79.947296    6.929772 79.947296
 6.929772 79.947296    6.vtet bztbt
 6.929772 79.947296    6.929772 79.947296

谁能告诉我这里出了什么问题?提前谢谢你。

【问题讨论】:

  • getLat() 返回自动变量的地址。一旦函数返回,该地址就不再有效,并且对该地址的任何取消引用甚至 eval 都会调用 未定义的行为
  • 我将缓冲区声明为堆变量。现在看来还可以。谢谢!
  • 希望您使用了智能指针。祝你好运。
  • 我对指针不是很有经验。我将通过互联网学习最佳实践。如果您有任何建议,我很乐意听到。
  • 你做得很好,采取主动很重要。在 this 端搜索 C++ 智能指针。关于 C++11 及其产品的最佳参考资料可以在cppreference.com 找到。如果你每天花 30-60 分钟在那个网站上阅读一些对你来说是新的东西,然后使用你在小示例程序中学到的东西,你的技能就会蓬勃发展。花时间与他们的样品。这是值得的,相信我。

标签: c++ string arduino string-concatenation


【解决方案1】:

如果您将代码更改为实用且简单的“helloworld.cpp”文件并使用 GNU C++ 编译器对其进行编译,则会警告您当前如何返回指向堆上被破坏的对象的指针的问题当 getLat() 超出范围时:

#include <stdio.h>
#include <string.h>

char* getLat();

int main(int argc, char **argv)
{
    char test[20] = {0};
    strncpy(test,getLat(),10);
    fprintf(stdout, "%s\n", test);
    return 1;
}

char* getLat(){
  char buffer[10] = {0};
  memset(buffer,0,sizeof(buffer));
  strcpy(buffer, "Testycole");
  // dtostrf(flat, 3, 6, buffer);
  // Serial.write(buffer);
  // Serial.print(" ");
  return buffer;
}

编译:

$ g++ file.cpp 
file.cpp: In function ‘char* getLat()’:
file.cpp:16:8: warning: address of local variable ‘buffer’ returned [-Wreturn-local-addr]
   char buffer[10] = {0};

在运行时,我看到垃圾:

$ a.out
 ��

一个快速的解决方法,但不一定是最好的解决方法,是在堆上而不是在 getLat() 的范围内分配缓冲区变量。像这样更改 GetLat() 代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char* getLat();

int main(int argc, char **argv)
{
    char test[20] = {0};
    char *heapBuffer = getLat();
    strncpy(test,heapBuffer,10);
    fprintf(stdout, "%s\n", test);
    //delete[] heapBuffer; // C++ deallocation; prevents memory leak.
    free(heapBuffer);    // C deallocation; prevents memory leak.

    return 1;
}


char* getLat(){
  //char *buffer = new char[10]; // C++ allocation
  char *buffer = (char*)malloc(10); // C allocation - to be a C purist.

  memset(buffer,0,sizeof(buffer));
  strcpy(buffer, "Testycole");
  // dtostrf(flat, 3, 6, buffer);
  // Serial.write(buffer);
  // Serial.print(" ");
  return buffer;
}

...这会产生更好的结果:

$ a.out
Testycole

不要忘记,在完成 char[10] 缓冲区对象后,您必须释放堆内存,否则您会发生内存泄漏。 :-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多