1

I'm working on an Arduino project and I need to use HMC5883L sensor's libraries. The problem is that the libraries are kind old and my compiler is complaining about the 'return' from a function:

/home/leandro/arduino-1.6.1/libraries/HMC5883L/HMC5883L.cpp: In member function 'uint8_t* HMC5883L::Read(int, int)':
/home/leandro/arduino-1.6.1/libraries/HMC5883L/HMC5883L.cpp:124:11: warning: address of local variable 'buffer' returned [-Wreturn-local-addr]
uint8_t buffer[length];

The part of the code is:

HMC5883L.cpp

uint8_t* HMC5883L::Read(int address, int length)
{
  Wire.beginTransmission(HMC5883L_Address);
  Wire.write(address);
  Wire.endTransmission();

  Wire.beginTransmission(HMC5883L_Address);
  Wire.requestFrom(HMC5883L_Address, length);

  uint8_t buffer[length]; // Here is line 124
  if(Wire.available() == length)
  {
      for(uint8_t i = 0; i < length; i++)
      {
          buffer[i] = Wire.read();
      }
  }
  Wire.endTransmission();

  return buffer;
}

HMC5883L.h:

#ifndef HMC5883L_h
#define HMC5883L_h

#include <Arduino.h>
#include <Wire.h>

#define HMC5883L_Address 0x1E
#define ConfigurationRegisterA 0x00
#define ConfigurationRegisterB 0x01
#define ModeRegister 0x02
#define DataRegisterBegin 0x03

#define Measurement_Continuous 0x00
#define Measurement_SingleShot 0x01
#define Measurement_Idle 0x03

#define ErrorCode_1 "Entered scale was not valid, valid gauss values are: 0.88, 1.3, 1.9, 2.5, 4.0, 4.7, 5.6, 8.1"
#define ErrorCode_1_Num 1

struct MagnetometerScaled
{
    float XAxis;
    float YAxis;
    float ZAxis;
};

struct MagnetometerRaw
{
    int XAxis;
    int YAxis;
    int ZAxis;
};

class HMC5883L
{
    public:
      HMC5883L();

      MagnetometerRaw ReadRawAxis();
      MagnetometerScaled ReadScaledAxis();

      int SetMeasurementMode(uint8_t mode);
      int SetScale(float gauss);

      const char* GetErrorText(int errorCode);

    protected:
      void Write(int address, int byte);
      uint8_t* Read(int address, int length);

    private:
      float m_Scale;
};
#endif

I tried few suggestions from here, here and here without success. Maybe I just couldn't figure out on how to solve this issue using those suggestion.

EDIT: There was an typo on my code, just changed it.

Community
  • 1
  • 1
Leandro
  • 1,114
  • 1
  • 12
  • 15
  • 1
    I can't believe that this is really code which was provided in a library. `uint8_t *buffer[length];` is complete broken. First it is an array of pointers and not an array and it is allocated on the stack of the function and later returned which never works. – Klaus May 06 '15 at 16:51
  • My mistake, I was performing some tests and I left this behind. I edited my post with the correct code. – Leandro May 06 '15 at 16:53

3 Answers3

4

Solution 1

Instead of

uint8_t buffer[length]; // Here is line 124

Use:

// Allocate memory from the heap.
uint8_t* buffer = new unit8_t[length];

Make sure to deallocate the memory in the calling function.

Solution 2

Expect the input to come from the calling function.

uint8_t* HMC5883L::Read(int address, int length, uint8_t buffer[])
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • There needs to be a check to verify there is only one allocation of the buffer inside the function. Try calling the function 2 times and verify. – Thomas Matthews May 06 '15 at 16:56
2

It is because you declare buffer on the stack. If you want to return a dynamically allocated buffer, use malloc:

uint8_t *buffer = new uint8_t[length];
if (buffer == NULL) error_allocation;

// Make sure to de-allocate after you finish to use it
delete [] buffer;
GHugo
  • 2,584
  • 13
  • 14
  • 1
    Where's the `malloc` call in your example? – Thomas Matthews May 06 '15 at 16:54
  • My mistake, I was performing some tests and I left this behind. I edited my post with the correct code. – Leandro May 06 '15 at 16:54
  • How does your example prevent multiple allocations of the buffer? Remember, the memory can't be deleted until after the function exits. – Thomas Matthews May 06 '15 at 16:55
  • It is C++, so one must use `new` and `delete` keywords : https://arduino.land/FAQ/content/4/20/en/can-i-use-new-and-delete-with-arduino.html. And it does not prevent memory to be allocated twice, but it is up to the programmer to take care of this. – GHugo May 06 '15 at 16:59
1

A simple solution is to modify the library files and declare the buffer as static. The static keyword tells the compiler that the variable will live after the execution leaves the function. Since it lives after exiting the function, the address will still be valid.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154