2017-02-08 9 views
0

誰かが私のC++プログラムに助けてくれますか?セグメント違反が発生しており、問題を見つけることができません。私はnRF24L01センサーネットワークと通信し、CURLを使用して自分のRPiでホストされているダッシュボード(Dashing)にデータを送信するラズベリーパイのプログラムを作成しています。C++:プロシージャから復帰するときのmemset()のセグメンテーションエラー

私は、デバッガ(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のと私のプログラムを確認 - リークチェック=フル。出力:

==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

ようこそスタックオーバーフロー!コードを編集して問題の[mcve]に減らしてください。あなたの現在のコードには、問題の周辺にあるものが多く含まれています。通常、最小単位のサンプルは良い単位テストと似ています。 –

答えて

-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 & POSTFIELDS)で常に同じオプションを設定しているので、私はリセットをする必要はないと思うので、これは私のために働く。

関連する問題