Search code examples
c++raspberry-pisegmentation-faultwiringpi

Segmentation fault with wiringPi


I'm fairly new to coding, and I've been trying to write something to write a placeholder to a text document whenever a button attached to a GPIO pin on my RasPi is pressed:

//Write date function//
void record() {

    ofstream myFile;
    myFile.open("report.txt");
    myFile << "Input at SPAM \n";
    myFile.close();

}

//myRead function//
void myRead(int i){

    if((digitalRead(4) == HIGH) && (i<5)) {
        record();
        digitalWrite(14, HIGH);
        delay(500);
        digitalWrite(14, LOW);  
        ++i;
        delay(500);
        myRead(i);
    }   
    else{
        if((digitalRead(4) != HIGH) && (i<5)){      
            myRead(i);
        }
    }

}   

int main() {
    wiringPiSetup();
    pinMode(12, OUTPUT);
    pinMode(14, OUTPUT);
    pinMode(4, INPUT);
    digitalWrite(12, HIGH);
    digitalWrite(14, LOW);

    myRead(1);
    digitalWrite(14, HIGH);
    delay(5000);
    digitalWrite(14, LOW);

    return 0;
}

The code compiles without any complaints, but if I run it in terminal without a sudo command, I get a "segmentation fault" error.
When I run it with a sudo command, the program starts and then ends almost immediately.

For reference:

  • Pin 12 is providing power to a potential divider on the breadboard.
  • Pin 4 should take the input from this divider.
  • Pin 14 causes an LED to light whenever there is an input on pin 4.

Whenever I run the program and VERY QUICKLY press the button on the potential divider, the LED will light if I hold the button.

How can I get this to run properly without it stopping as soon as it starts?


Solution

  • I think there are several possible problems with myRead.

    A minor rewrite could be:

    void myRead(int i)
    {
        if((digitalRead(4) == HIGH) && (i<5)) {
            record();
            digitalWrite(14, HIGH);
            delay(500);
            digitalWrite(14, LOW);  
            ++i;
            delay(500);
            myRead(i);
        } else if((digitalRead(4) != HIGH) && (i<5)) {
            myRead(i);
        }
    }
    

    Notice that you have two calls to digitalRead -- this may lead to problems since the first one my return something different from HIGH and the second may return HIGH, meaning neither conditions are true.

    You make a call to myRead with the same i in the alternative branch as the original call. If digitalRead returns something different from HIGH suffeciently many times, your stack will be full very fast and you'll get a segfault.

    I'll propose a different version, that should be identical (baring any misunderstanding on my part):

    void myRead(int i)
    {
        // as long as i is less than 5
        while (i < 5) {
            // busy wait for digitalRead(4) to be HIGH
            while (digitalRead(4) != HIGH);
            // do the main thing
            record();
            digitalWrite(14, HIGH);
            delay(500);
            digitalWrite(14, LOW);  
            ++i;
            delay(500);
        }
    }
    

    Also please note that this is just plain C, not C++ (well, technically it's valid C++, but it's making no use of C++)