有人可以帮我解决我的C ++程序吗?我遇到了分段错误,我找不到问题。我正在为我的raspberry pi编写一个程序,它与nRF24L01传感器网络通信,并使用CURL将数据发送到我的RPi上托管的仪表板(Dashing)。
我用调试器(gdb)运行我的程序,这是我得到的回溯:(见完整源代码见下文)
Program received signal SIGSEGV, Segmentation fault.
0xb6fbe0dc in memset () from /usr/lib/arm-linux-gnueabihf/libarmmem.so
(gdb) bt
#0 0xb6fbe0dc in memset () from /usr/lib/arm-linux-gnueabihf/libarmmem.so
#1 0x000119d4 in handleSensorMsg () at myNetworkMaster.cpp:174
#2 0x00000000 in ?? ()
我还用valgrind检查了我的程序,使用--leak-check = full。输出:
==20790== Invalid read of size 4
==20790== at 0x484F808: bcm2835_peri_read (in /usr/local/lib/librf24.so.1.1.7)
==20790== Address 0xffffffff is not stack'd, malloc'd or (recently) free'd
==20790==
==20790==
==20790== Process terminating with default action of signal 11 (SIGSEGV)
==20790== Access not within mapped region at address 0xFFFFFFFF
==20790== at 0x484F808: bcm2835_peri_read (in /usr/local/lib/librf24.so.1.1.7)
==20790== If you believe this happened as a result of a stack
==20790== overflow in your program's main thread (unlikely but
==20790== possible), you can try to increase the size of the
==20790== main thread stack using the --main-stacksize= flag.
==20790== The main thread stack size used in this run was 8388608.
==20790==
==20790== HEAP SUMMARY:
==20790== in use at exit: 75,908 bytes in 643 blocks
==20790== total heap usage: 1,232 allocs, 589 frees, 84,668 bytes allocated
==20790==
==20790== LEAK SUMMARY:
==20790== definitely lost: 0 bytes in 0 blocks
==20790== indirectly lost: 0 bytes in 0 blocks
==20790== possibly lost: 0 bytes in 0 blocks
==20790== still reachable: 75,908 bytes in 643 blocks
==20790== suppressed: 0 bytes in 0 blocks
==20790== Reachable blocks (those to which a pointer was found) are not shown.
==20790== To see them, rerun with: --leak-check=full --show-reachable=yes
==20790==
==20790== For counts of detected and suppressed errors, rerun with: -v
==20790== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
源代码:在第一次调用sendDataToDashBoard()之后,在handleSensorMsg()中发生崩溃。会发生什么是程序启动并侦听nRF24L01上的消息。它将收到的第一个是传感器消息。它读取内容并将温度数据发送到仪表板。之后会崩溃。正如你所看到的,我不习惯用C(++)编程,我的经验仅限于一些简单的arduino程序。
/** use Raspberry pi as master node for RF24Network, based on example code from TMRh20
*
* This example sketch shows how to manually configure a node via RF24Network as a master node, which
* will receive all data from sensor nodes.
*
* send received data to Dashing dashboard using curl
*
* listen for messages on the program queue to send data to a node
*
*/
#include <RF24/RF24.h>
#include <RF24Network/RF24Network.h>
#include <curl/curl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <mqueue.h>
#include <time.h>
#include "common.h"
/**
* g++ -L/usr/lib main.cc -I/usr/include -o main -lrrd
**/
//using namespace std;
// CE Pin, CSN Pin, SPI Speed
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
//RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ);
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);
RF24Network network(radio);
CURL *curl;
//CURLcode res;
mqd_t mq;
const char* AUTH_TOKEN = "MODEL_M";
const char* DASHBOARD_IP = "http://192.168.0.21:80/";
const int CURL_BUFFER_SIZE = 100;
class timer {
private:
time_t begTime;
public:
bool isRunning = false;
void start() {
begTime = time(NULL);
isRunning = true;
}
int elapsedTime() {
return (time(NULL) - begTime);
}
bool isTimeout(int seconds) {
int elapsed = elapsedTime();
//printf("%f\n", elapsed);
return elapsed >= seconds;
}
};
const int AVG_TEMP_SAMPLESIZE = 60;
const float TEMP_HIVAL = 999;
const float TEMP_LOVAL = -273.15;
const int DAILY_TEMP_RST_HOUR = 0;
float avgTemperature = TEMP_HIVAL;
float minTemperature = TEMP_HIVAL;
float maxTemperature = TEMP_LOVAL;
float minDailyTemp = TEMP_HIVAL;
float maxDailyTemp = TEMP_LOVAL;
// TODO: create 'message queue'?
const int SEND_RELAY_INTERVAL = 1;
timer relayMsgTimer;
const int SEND_DASH_WAIT = 1;
timer relayDashTimer;
const int SEND_QUERY_INTERVAL = 10;
timer queryMsgTimer;
bool timedRelayMode = true;
int timedRelayState = 1;
const int TIMED_RELAY_ON_HOUR = 6;
const int TIMED_RELAY_OFF_HOUR = 0;
const int TIMED_RELAY_RST_HOUR = 12;
void setCurrentTimestamp(char* timestamp) {
time_t rawTime = time(NULL);
struct tm *tm = localtime(&rawTime);
strftime(timestamp, 20, "%Y-%m-%d %H:%M:%S", tm);
}
void sendDataToDashBoard(const char* const widget, const char* const data) {
char url[CURL_BUFFER_SIZE];
char postFields[CURL_BUFFER_SIZE];
std::fill(url, url + CURL_BUFFER_SIZE, 0);
std::fill(postFields, postFields + CURL_BUFFER_SIZE, 0);
sprintf(url, "%swidgets/%s", DASHBOARD_IP, widget);
curl_easy_setopt(curl, CURLOPT_URL, url);
sprintf(postFields, "{\"auth_token\":\"%s\",%s", AUTH_TOKEN, data);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postFields);
printf("%s%s\n", url, postFields);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
printf("curl_easy_perform failed: %s\n", curl_easy_strerror(res));
curl_easy_reset(curl);
} // <-- this is where the debugger stops !!!
void handleSensorMsg() {
RF24NetworkHeader header = 0;
network.read(header,&sensorData,sizeof(sensorData));
char timestamp[20];
std::fill(timestamp, timestamp + 20, 0);
setCurrentTimestamp(timestamp);
printf("%s - %c: Rcv %d %u from 0%o\n", timestamp, SENSOR_MSG, sensorData.temperature, sensorData.humidity, header.from_node);
// ignore probable invalids -- TODO: what if first reading is invalid? => avgTemperature
if (header.from_node != SENSOR_NODE ||
(avgTemperature != TEMP_HIVAL &&
(sensorData.temperature > avgTemperature * 20.0 ||
sensorData.temperature < avgTemperature * 5.0))) {
printf("ignored invalid data\n");
return;
}
float temperature = sensorData.temperature / 10.0;
int humidity = sensorData.humidity / 10.0 + 0.5;
if (avgTemperature == TEMP_HIVAL)
avgTemperature = temperature;
else {
avgTemperature -= avgTemperature / AVG_TEMP_SAMPLESIZE;
avgTemperature += temperature / AVG_TEMP_SAMPLESIZE;
}
if (temperature > maxDailyTemp) {
maxDailyTemp = temperature;
if (temperature > maxTemperature)
maxTemperature = temperature;
} else if (temperature < minDailyTemp) {
minDailyTemp = temperature;
if (temperature < minTemperature)
minTemperature = temperature;
}
char data[CURL_BUFFER_SIZE];
std::fill(data, data + CURL_BUFFER_SIZE, 0);
sprintf(data, "\"current\":%.1f,\"average\":%f,\"moreinfo\":\"Min : %.1f (%.1f) - Max : %.1f (%.1f)\"}",
temperature, avgTemperature, minDailyTemp, minTemperature, maxDailyTemp, maxTemperature);
sendDataToDashBoard("temperature", data); // This is the call that crashes!!!
std::fill(data, data + CURL_BUFFER_SIZE, 0);
sprintf(data, "\"value\":%d}", humidity);
sendDataToDashBoard("humidity", data);
}
void handleRelayMsg() {
RF24NetworkHeader header = 0;
network.read(header, &relayData, sizeof(relayData));
char timestamp[20];
std::fill(timestamp, timestamp + 20, ' ');
setCurrentTimestamp(timestamp);
printf("%s - %c: Rcv %d from 0%o\n", timestamp, RELAY_MSG, relayData.state, header.from_node);
// handle invalid reading
if (header.from_node != RELAY_NODE ||
(relayData.state != true && relayData.state != false)) {
printf("ignored invalid data\n");
queryMsgTimer.start();
return;
}
// delay send of relayData to dashboard to avoid race condition
relayDashTimer.start();
relayMsgTimer.isRunning = false;
queryMsgTimer.isRunning = false;
}
bool sendRelayData() {
RF24NetworkHeader header(/*to node*/ RELAY_NODE, RELAY_MSG);
char timestamp[20];
std::fill(timestamp, timestamp + 20, ' ');
setCurrentTimestamp(timestamp);
printf("%s - %c: Snd %d to %o\n", timestamp, RELAY_MSG, relayData.state, RELAY_NODE);
if (!network.write(header, &relayData, sizeof(relayData))) {
relayMsgTimer.start();
printf("Send failed...\n");
return false;
}
printf("Send OK\n");
return true;
}
void sendQueryMsgToRelay() {
RF24NetworkHeader header(/*to node*/ RELAY_NODE, QUERY_MSG);
char timestamp[20];
std::fill(timestamp, timestamp + 20, ' ');
setCurrentTimestamp(timestamp);
printf("%s - %c: Snd to %o\n", timestamp, QUERY_MSG, RELAY_NODE);
if (!network.write(header, NULL, 0)) {
queryMsgTimer.start();
printf("Send failed...\n");
return;
}
printf("Send OK\n");
queryMsgTimer.isRunning = false;
}
bool readMessageQueue() {
ssize_t bytes_read;
char buffer[MAX_SIZE + 1];
std::fill(buffer, buffer + MAX_SIZE + 1, ' ');
/* receive the message */
bytes_read = mq_receive(mq, buffer, MAX_SIZE, NULL);
if (bytes_read >= 0) {
buffer[bytes_read] = '\0';
char timestamp[20];
std::fill(timestamp, timestamp + 20, ' ');
setCurrentTimestamp(timestamp);
printf("%s - Received: %s\n", timestamp, buffer);
if (!strncmp(buffer, MSG_ON, strlen(MSG_ON))) {
if (relayMsgTimer.isRunning)
return false;
relayData.state = true;
queryMsgTimer.isRunning = false;
sendRelayData();
} else if (!strncmp(buffer, MSG_OFF, strlen(MSG_OFF))) {
if (relayMsgTimer.isRunning)
return false;
relayData.state = false;
queryMsgTimer.isRunning = false;
sendRelayData();
} else if (!strncmp(buffer, MSG_SET, strlen(MSG_SET))) {
if (relayMsgTimer.isRunning)
return false;
relayData.state = !relayData.state;
queryMsgTimer.isRunning = false;
sendRelayData();
} else if (!strncmp(buffer, MSG_GET, strlen(MSG_GET))) {
if (queryMsgTimer.isRunning)
return false;
sendQueryMsgToRelay();
} else if (!strncmp(buffer, MSG_TIMER, strlen(MSG_TIMER))) {
timedRelayMode = !timedRelayMode;
timedRelayState = 1;
printf("timedRelayMode=%d\n", timedRelayMode);
} else if (!strncmp(buffer, MSG_STOP, strlen(MSG_STOP)))
return true;
}
return false;
}
void sendRelayDataToDashboard() {
char data[CURL_BUFFER_SIZE];
std::fill(data, data + CURL_BUFFER_SIZE, 0);
sprintf(data, "\"status\":\"%s\"}", relayData.state ? "ON" : "OFF");
sendDataToDashBoard("relay", data);
relayDashTimer.isRunning = false;
}
int getCurrentHour() {
time_t rawTime = time(NULL);
struct tm *tm = localtime(&rawTime);
return tm->tm_hour;
}
void setTimedRelayState() {
char timestamp[20];
std::fill(timestamp, timestamp + 20, ' ');
setCurrentTimestamp(timestamp);
printf("%s - Timed relay event:\n", timestamp);
relayData.state = !relayData.state;
sendRelayData();
}
void updateTimedRelay(int hour) {
if (timedRelayState == 1 && relayData.state && hour == TIMED_RELAY_OFF_HOUR) {
setTimedRelayState();
timedRelayState = 2;
} else if (timedRelayState == 2 && !relayData.state && hour == TIMED_RELAY_ON_HOUR) {
setTimedRelayState();
timedRelayState = 1;
} else if (timedRelayState == 2 && hour == TIMED_RELAY_RST_HOUR)
timedRelayState = 1;
}
void updateDailyTemperature(int hour) {
if (hour == DAILY_TEMP_RST_HOUR) {
char timestamp[20];
std::fill(timestamp, timestamp + 20, ' ');
setCurrentTimestamp(timestamp);
minDailyTemp = avgTemperature;
maxDailyTemp = avgTemperature;
printf("%s - daily temperatures reset\n", timestamp);
}
}
int main(int argc, char** argv)
{
// Refer to RF24.h or nRF24L01 DS for settings
radio.begin();
delay(5);
network.begin(CHANNEL, MASTER_NODE);
radio.setDataRate(RF24_250KBPS);
radio.setCRCLength(RF24_CRC_8);
// increase delay for network ACK
network.routeTimeout = 300;
radio.printDetails();
// CURL setup for sending data to dashboard
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl == NULL) {
printf("Error getting curl handle.\n");
exit(EXIT_FAILURE);
}
// setup the message queue
struct mq_attr attr;
/* initialize the queue attributes */
attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = MAX_SIZE;
attr.mq_curmsgs = 0;
/* create the message queue */
mq = mq_open(QUEUE_NAME, O_CREAT | O_RDONLY | O_NONBLOCK, 0644, &attr);
if (mq == -1) {
printf("Failed to create queue.\n");
exit(EXIT_FAILURE);
}
queryMsgTimer.start();
int currentHour = getCurrentHour();
bool exitReceived = false;
while(!exitReceived)
{
network.update();
while ( network.available() ) { // Is there anything ready for us?
RF24NetworkHeader header; // If so, grab it and print it out
network.peek(header);
switch(header.type) {
case SENSOR_MSG: handleSensorMsg();
break;
case RELAY_MSG: handleRelayMsg();
break;
default: network.read(header,0,0);
char timestamp[20];
setCurrentTimestamp(timestamp);
printf("%s - Rcv bad type %d from 0%o\n", timestamp, header.type, header.from_node);
printf("%s\n", header.toString());
break;
}
}
// check for incoming messages on the program queue
exitReceived = readMessageQueue();
// are there any messages that need to be sent?
if (relayMsgTimer.isRunning && relayMsgTimer.isTimeout(SEND_RELAY_INTERVAL))
relayMsgTimer.isRunning = !sendRelayData();
if (relayDashTimer.isRunning && relayDashTimer.isTimeout(SEND_DASH_WAIT))
sendRelayDataToDashboard();
if (queryMsgTimer.isRunning && queryMsgTimer.isTimeout(SEND_QUERY_INTERVAL))
sendQueryMsgToRelay();
// timed events
if (currentHour != getCurrentHour()) {
currentHour = getCurrentHour();
// check if relay needs to be switched on or off based on timer
if (timedRelayMode)
updateTimedRelay(currentHour);
// reset daily temperature min&max
updateDailyTemperature(currentHour);
}
delay(100);
fflush(stdout);
}
/* cleanup */
curl_easy_cleanup(curl);
curl_global_cleanup();
mq_close(mq);
mq_unlink(QUEUE_NAME);
return 0;
}
common.h包括:
#ifndef COMMON_H_
#define COMMON_H_
#define CHANNEL 1
#define QUEUE_NAME "/rf24_queue"
#define MAX_SIZE 1024
#define MSG_STOP "exit"
#define MSG_ON "ON"
#define MSG_OFF "OFF"
#define MSG_SET "SET"
#define MSG_GET "GET"
#define MSG_TIMER "TIMER"
#define MASTER_NODE 0
#define SENSOR_NODE 01
#define RELAY_NODE 01
#define SENSOR_MSG '1'
#define RELAY_MSG 'R'
#define QUERY_MSG 'Q'
#ifndef AM2320_H
struct sensorData_t {
int16_t temperature;
uint16_t humidity;
} sensorData;
#endif
struct relayData_t {
bool state;
} relayData;
typedef enum { wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s } wdt_prescalar_e;
#endif /* #ifndef COMMON_H_ */
RF24库可从此处获得:https://github.com/TMRh20/RF24。谢谢你的时间!
答案 0 :(得分:-1)
违规代码就是这个块(在sendDataToDashBoard中):
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
printf("curl_easy_perform failed: %s\n", curl_easy_strerror(res));
curl_easy_reset(curl);
我注释掉了curl_easy_reset()调用,现在它不再崩溃了。我不知道为什么,但你有它。我想我不需要重置,因为我总是在每次执行时设置相同的选项(URL&amp; POSTFIELDS),所以这对我有用。