2017-02-08 5 views
0

누구든지 내 C++ 프로그램을 도와 줄 수 있습니까? 세그먼트 오류가 발생하여 문제를 찾을 수 없습니다. 나는 nRF24L01 센서 네트워크와 통신하고 CURL을 사용하여 RPi에서 호스팅되는 대시 보드 (Dashing)에 데이터를 전송하는 라즈베리 파이 프로그램을 작성하고 있습니다.C++ : 프로 시저에서 복귀 할 때 memset()의 세그먼테이션 오류

나는 디버거 (GDB) 내 프로그램을 실행, 그리고 이것은 내가 가진 역 추적입니다 : (전체 소스 코드를 아래 참조) 나는 또한 사용 Valgrind의 내 프로그램을 확인

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 ??() 

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

소스 코드 : 충돌 handleSensorMsg (발생) sendDataToDashBoard 최초의 호출 후(). 그러면 프로그램이 시작되어 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. 시간 내 줘서 고마워!

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() 호출에서 주석과 지금은 더 이상 충돌하지 않습니다

+0

스택 오버플로에 오신 것을 환영합니다! 코드를 편집하여 문제의 [mcve]로 줄이십시오. 현재 코드에는 문제의 주변부가 많이 포함되어 있습니다. 최소한의 샘플은 일반적으로 좋은 단위 테스트와 유사합니다. 재현성을 위해 지정된 입력 값을 사용하여 하나의 작업 만 수행합니다. –

답변

-1

기분을 상하게하는 코드는 여기 (sendDataToDashBoard에서)이 블록이었다. 나는 왜 그런지 모르지만 당신은 그것을 가지고 있습니다. 나는 항상 모든 공연 (URL &)에 동일한 옵션을 설정했기 때문에 리셋을 할 필요가 없다고 생각한다.