Arduino C++ for循环提前退出?
Arduino C++ for loop exiting early?
下午的大部分时间我都在盯着这个看,结果被难住了。这个问题看起来很简单,我敢肯定这将是一个真正的 Doh!掰开时的脸掌瞬间
一些背景:
我正在创建一个小项目,使用 Arduino 从我的遥控器读取红外信号并将它们发送到我正在编写的 Python 程序。
我将示例命令作为 JSON 字符串发送到 Arduino,并使用 Arduinojson 库对其进行反序列化。那很好用。我的采样方法捕获信号并将其写入一个 int 数组。
我苦苦挣扎的地方是将该数组转换为 JSON 字符串。我尝试使用相同的库对其进行序列化,但它占用了大量内存,因此我尝试编写一个循环将整数转换为字符串形式并从中手动构造一个 JSON 字符串。
我的信号捕捉方式:
// Capture an IR signal
bool capture() {
bool captured = false;
if(myReceiver.getResults()) {
int index = 0;
for(bufIndex_t i = 1; i < recvGlobal.recvLength; i++){
irBuffer[index++] = recvGlobal.recvBuffer[i];
// Debug
Serial.print(i);
Serial.print(" - ");
Serial.println(recvGlobal.recvBuffer[i]);
}
irBuffer[index] = 0;
captured = true;
}
myReceiver.enableIRIn();
return captured;
}
该方法的调试输出显示我捕获了 67 个脉冲:
1 - 4400
2 - 4600
3 - 550
4 - 600
5 - 550
6 - 550
7 - 550
8 - 1650
9 - 550
10 - 1700
11 - 550
12 - 600
13 - 550
14 - 1650
15 - 600
16 - 550
17 - 550
18 - 600
19 - 500
20 - 600
21 - 550
22 - 550
23 - 550
24 - 1700
25 - 550
26 - 1650
27 - 550
28 - 600
29 - 550
30 - 1700
31 - 550
32 - 600
33 - 500
34 - 600
35 - 550
36 - 550
37 - 550
38 - 1700
39 - 550
40 - 1650
41 - 550
42 - 1700
43 - 550
44 - 1700
45 - 550
46 - 600
47 - 500
48 - 600
49 - 550
50 - 600
51 - 500
52 - 1700
53 - 550
54 - 600
55 - 550
56 - 550
57 - 550
58 - 600
59 - 500
60 - 600
61 - 500
62 - 1700
63 - 600
64 - 1650
65 - 550
66 - 1700
67 - 550
我尝试将其转换为 JSON 字符串:
#define MAX_IR 100
...
if (RETURN_IR_SIGNAL) {
char out[MAX_IR];
char tmp[10];
strcpy(out, "{\"signal\":[");
for (int i = 0; i <= MAX_IR; i++) {
if (irBuffer[i] == 0) {
break;
}
// Debug statements
Serial.print("out = ");
Serial.println(out);
sprintf(tmp, "%d,", irBuffer[i]);
strcat(out, tmp);
}
strcat(out, "]}");
// Debug
Serial.println("Finished");
RETURN_IR_SIGNAL = false;
}
该代码的调试输出是这样的:
out = {"signal":[
out = {"signal":[4400,
out = {"signal":[4400,4600,
out = {"signal":[4400,4600,550,
out = {"signal":[4400,4600,550,600,
out = {"signal":[4400,4600,550,600,550,
out = {"signal":[4400,4600,550,600,550,550,
out = {"signal":[4400,4600,550,600,550,550,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,550,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,550,550,600,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,550,550,600,500,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,550,550,600,500,600,
out = {"signal":[4400,4600,550,600,550,550,55�␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀
您可以看到,当它到达数组中的第 21 个数字时,它会将字符串截断为少数几个数字。此外,我没有看到最终的“已完成”消息这一事实表明我可能会抛出异常并重新启动,但我无法确定是否是这种情况。
自从我编写任何 C 或 C++ 以来已经有二十多年了,所以这是一场艰苦的战斗,但很愉快。所以我敢说这是一个典型的菜鸟错误,但它让我望而却步。
非常感谢任何帮助。
您的代码
strcat(out, tmp);
会导致最终的堆栈缓冲区溢出,因为 out
缓冲区的大小仅为 100 个字符 (不是整数),但您要写入的内容远不止于此一个迭代阶段后的字符缓冲区(准确地说是第 20 次迭代)。
我在启用 ASAN 的情况下编译了您的代码片段(-fsanitize=address
) and it was easy to figure out the error. I hope resolving that issue should iron out this anomaly in printing, provided serial logging on the board accommodates such long strings. You could probably use std::string
or use an intermediate std::vector
, coupled with std::to_string
然后将其字符串化并转储到控制台。
下午的大部分时间我都在盯着这个看,结果被难住了。这个问题看起来很简单,我敢肯定这将是一个真正的 Doh!掰开时的脸掌瞬间
一些背景:
我正在创建一个小项目,使用 Arduino 从我的遥控器读取红外信号并将它们发送到我正在编写的 Python 程序。
我将示例命令作为 JSON 字符串发送到 Arduino,并使用 Arduinojson 库对其进行反序列化。那很好用。我的采样方法捕获信号并将其写入一个 int 数组。
我苦苦挣扎的地方是将该数组转换为 JSON 字符串。我尝试使用相同的库对其进行序列化,但它占用了大量内存,因此我尝试编写一个循环将整数转换为字符串形式并从中手动构造一个 JSON 字符串。
我的信号捕捉方式:
// Capture an IR signal
bool capture() {
bool captured = false;
if(myReceiver.getResults()) {
int index = 0;
for(bufIndex_t i = 1; i < recvGlobal.recvLength; i++){
irBuffer[index++] = recvGlobal.recvBuffer[i];
// Debug
Serial.print(i);
Serial.print(" - ");
Serial.println(recvGlobal.recvBuffer[i]);
}
irBuffer[index] = 0;
captured = true;
}
myReceiver.enableIRIn();
return captured;
}
该方法的调试输出显示我捕获了 67 个脉冲:
1 - 4400
2 - 4600
3 - 550
4 - 600
5 - 550
6 - 550
7 - 550
8 - 1650
9 - 550
10 - 1700
11 - 550
12 - 600
13 - 550
14 - 1650
15 - 600
16 - 550
17 - 550
18 - 600
19 - 500
20 - 600
21 - 550
22 - 550
23 - 550
24 - 1700
25 - 550
26 - 1650
27 - 550
28 - 600
29 - 550
30 - 1700
31 - 550
32 - 600
33 - 500
34 - 600
35 - 550
36 - 550
37 - 550
38 - 1700
39 - 550
40 - 1650
41 - 550
42 - 1700
43 - 550
44 - 1700
45 - 550
46 - 600
47 - 500
48 - 600
49 - 550
50 - 600
51 - 500
52 - 1700
53 - 550
54 - 600
55 - 550
56 - 550
57 - 550
58 - 600
59 - 500
60 - 600
61 - 500
62 - 1700
63 - 600
64 - 1650
65 - 550
66 - 1700
67 - 550
我尝试将其转换为 JSON 字符串:
#define MAX_IR 100
...
if (RETURN_IR_SIGNAL) {
char out[MAX_IR];
char tmp[10];
strcpy(out, "{\"signal\":[");
for (int i = 0; i <= MAX_IR; i++) {
if (irBuffer[i] == 0) {
break;
}
// Debug statements
Serial.print("out = ");
Serial.println(out);
sprintf(tmp, "%d,", irBuffer[i]);
strcat(out, tmp);
}
strcat(out, "]}");
// Debug
Serial.println("Finished");
RETURN_IR_SIGNAL = false;
}
该代码的调试输出是这样的:
out = {"signal":[
out = {"signal":[4400,
out = {"signal":[4400,4600,
out = {"signal":[4400,4600,550,
out = {"signal":[4400,4600,550,600,
out = {"signal":[4400,4600,550,600,550,
out = {"signal":[4400,4600,550,600,550,550,
out = {"signal":[4400,4600,550,600,550,550,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,550,550,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,550,550,600,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,550,550,600,500,
out = {"signal":[4400,4600,550,600,550,550,550,1650,550,1700,550,600,550,1650,600,550,550,600,500,600,
out = {"signal":[4400,4600,550,600,550,550,55�␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀␀
您可以看到,当它到达数组中的第 21 个数字时,它会将字符串截断为少数几个数字。此外,我没有看到最终的“已完成”消息这一事实表明我可能会抛出异常并重新启动,但我无法确定是否是这种情况。
自从我编写任何 C 或 C++ 以来已经有二十多年了,所以这是一场艰苦的战斗,但很愉快。所以我敢说这是一个典型的菜鸟错误,但它让我望而却步。
非常感谢任何帮助。
您的代码
strcat(out, tmp);
会导致最终的堆栈缓冲区溢出,因为 out
缓冲区的大小仅为 100 个字符 (不是整数),但您要写入的内容远不止于此一个迭代阶段后的字符缓冲区(准确地说是第 20 次迭代)。
我在启用 ASAN 的情况下编译了您的代码片段(-fsanitize=address
) and it was easy to figure out the error. I hope resolving that issue should iron out this anomaly in printing, provided serial logging on the board accommodates such long strings. You could probably use std::string
or use an intermediate std::vector
, coupled with std::to_string
然后将其字符串化并转储到控制台。