C ++:从过程

时间:2017-02-08 08:19:16

标签: c++ segmentation-fault libcurl raspbian

有人可以帮我解决我的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。谢谢你的时间!

1 个答案:

答案 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),所以这对我有用。