1

I have a problem with the global variable calibrationValue. It is initially set with the correct value and is also displayed correctly in the output. As soon as the loop function is restarted, the value of the variable is wrong, although it is not rewritten. Can someone help me please? The following values ​​are printed in the image:

  1. new AI value
  2. wrong calibrationValue (!)
  3. sumOfValues (needed for calculation of calibrationValue) correct
  4. numValues (needed for calculation of calibrationValue) correct
  5. Text and calibrationValue (correct!)
 int op_mode_Pin = 7; // Digital input Pin which transmittes the op_mode_Ardui
 int op_mode_Ardui; // Operator Mode of Arduino
 int returnValue1 = 12; // First digital return value for transmitting box weight
 int returnValue2 = 13; // Second digital return value for transmitting box weight 
 
 int sensorPin = A0; // Select the input pin for the potentiometer
 long weightValue = 0; // Variable to store the value from the sensor
 long calibrationValue = 0; // Value which is filled in calibration progress
 int numValues = 50; // Number of taken values for calculating an average
 int thresBoxWeight = 300; // Weight for separating heavy and light boxes
 
 unsigned long sumOfValues; // Sum of the taken values
 unsigned long aveOfValues; // Average of the values
 
 char stringBuffer[30]; // Buffer for combining string and variables
 
 void setup() {
 // Initiate serial communication to screen
 Serial.begin(9600);
 
 // Initiate some variables 
 //weightValue = 0;
 //calibrationValue = 0;
 //numValues = 50;
 //thresBoxWeight = 300;
 
 // Set the Input Pins for op_mode_Ardui
 pinMode(op_mode_Pin, INPUT); // sets the digital pin 7 as input 
 
 // Set the Output Pins for Box declaration
 pinMode(returnValue1, OUTPUT); // sets the digital pin 12 as output 
 pinMode(returnValue2, OUTPUT); // sets the digital pin 13 as output
 
 }
 
 void loop() {
 Serial.println(analogRead(sensorPin));
 Serial.println(calibrationValue);
 // Reset of Sum and Average variables for next cycle
 sumOfValues = 0;
 aveOfValues = 0;
 op_mode_Ardui = digitalRead(op_mode_Pin);
 
 if (op_mode_Ardui == HIGH){
 for (int i=0; i<numValues; i++){
 weightValue = analogRead(sensorPin); // read the value from the sensor
 sumOfValues = sumOfValues + weightValue; // Build the sum of all values
 }
 Serial.println(sumOfValues);
 Serial.println(numValues);
 
 calibrationValue = sumOfValues / numValues;
 sprintf(stringBuffer, "Calibration accomplished with value: %d", calibrationValue); // Combine text and variable to output
 Serial.println(stringBuffer); // print text and variable to screen
 delay(3000);
 }
 }

enter image description here

asked Jul 15, 2020 at 19:05
0

1 Answer 1

1

This:

sprintf(stringBuffer, "Calibration accomplished with value: %d", calibrationValue);

is a buffer overflow: the function sprintf() is writing a 40-byte string into a 30-byte buffer. Whatever happens to lie in memory right after the buffer will be overwritten by sprintf(). Apparently this happened to be calibrationValue. You should use snprintf() rather that sprintf(), as the former is designed to prevent this kind of overflows.

Or better yet, stick with Serial.print[ln]():

Serial.print("Calibration accomplished with value: ");
Serial.println(calibrationValue);

Edit: You may notice that 13108 is the same as 0x3334, which on a little endian architecture is stored in memory as 0x34 0x33. These are the ASCII codes for "43", which is part of what sprintf() wrote past the end of the buffer.

answered Jul 15, 2020 at 19:18
4
  • it's interesting that the buffer overflow in stringBuffer overwrites a variable defined further up in the file. In most compilers your globals get allocated in memory roughly in the order you declare them. (Optimizing compilers on 32 and 64 bit platforms might do some re-ordering to make variable sized structures fit in less memory while honoring word/longword/double alignment, but most Arduinos are 8 bit devices where there's no such thing as word alignment.) Commented Jul 15, 2020 at 19:54
  • It worked. I never thought that an overflow could affect global variables. Thank you. Commented Jul 15, 2020 at 20:03
  • On a real mode machine like an Arduino, a buffer overflow stomps whatever is in RAM. Global variables, data on the heap, whatever. And there's nothing stopping it. Commented Jul 15, 2020 at 20:31
  • @DuncanC: I don't know how the linker decides on the allocation order. I tried compiling the OP's code with avr-g++ 7.3.0, as shipped with the Arduino IDE 1.8.13, and the .bss section contains timer0_fract, timer0_millis, timer0_overflow_count, stringBuffer, sumOfValues, calibrationValue and Serial, in this order. If I remove -flto from the compiler's command line, I get a different allocation starting with stringBuffer, aveOfValues (which was optimized out with -flto), sumOfValues, calibrationValue Commented Jul 15, 2020 at 21:16

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.