user8370061 user8370061 - 1 year ago 52
C++ Question

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? Sorry if the answer is obvious, as I say, I'm fairly new to coding.

Answer Source

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

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download