Why defining buffer length of a buffer leads to that class's function member to loose the value of a function pointer member variable?

Sanmveg saini

I am working with GNU AVR GCC version 5.4.0 and Atmelstudio 7.0.2397 and I have the following problem.


Problem Description

In the following Image, ye can see that up to line 13, the program has stored the address of function usart_send into the transmitter variable which is member of SimpleClass object sc.

enter image description here

The prototype of the transmitter function is void (*transmitter)(uint8_t * txbuff, uint8_t len); and usart_send function prototype definition is void usart_send(uint8_t *, uint8_t);.

Now when I step into the foo function, notice that when inside the member function of the class's object, the address of transmitter is now 0.

enter image description here

Similarly inside the function flush, its value is still 0. So I cannot call the desired function. And this is what disassembly is showing and so is my MCU.

enter image description here


Cause of this problem

So I have the following code for SimpleClass.h

#pragma once

typedef unsigned char uint8_t;

#ifndef rxBufferLen
#define rxBufferLen 30
#endif
#ifndef txBufferLen
#define txBufferLen 30
#endif

class SimpleClass{
    uint8_t rxbuffer[rxBufferLen]; ///< receiver buffer
    uint8_t txBuffer[txBufferLen]; ///< transmitter buffer
    uint8_t rxbuff_index, ///< rxbuffer index. Indicates where to put new data
    txbuff_index; ///< txBuffer index. Indicates where to put new data
    public:
    void (*transmitter)(uint8_t * txbuff, uint8_t len);
    void pushtx(uint8_t byte);
    void pushrx(uint8_t byte);
    void flush();
    void foo();
};

Notice that have the length of txBuffer and rxBuffer defined using define. And in incfile1.h I have the following code.

#pragma once

#define rxBufferLen 50
#define txBufferLen 50

#include <avr/io.h>
#include "simpleClass.h"

#define TIMER0_CLOCK_PRESCALAR  (3)
#define TIMER0_CLOCK_COUNT      (0xff - 50)

void usart_init();
void timer0_init();
void serial_send_ln(const char *);
void usart_send(uint8_t *, uint8_t);
void usart_send_ln(uint32_t num);

In here I have redefined rxBufferLen and txBufferLen. This definition of define causes the above problem. If I remove these two lines, this code is working fine.


Question

So you can see that by defining the buffer length for a buffer which is inside a class, causes its member function to loose the value the class's function pointer (which is a member variable). And I want to know why?


Code

Here are many un used functions and this is because I was isolating bug(if it is a bug!) from my project.

main.cpp

#include "IncFile1.h"

SimpleClass sc;

int main(void)
{
    
    usart_init();
    timer0_init();
    
    sc.transmitter = &usart_send;
    sc.foo();
    
    
    while (1) 
    {
    }
}

IncFile.h

#pragma once

#define rxBufferLen 50
#define txBufferLen 50

#include <avr/io.h>
#include "simpleClass.h"

#define TIMER0_CLOCK_PRESCALAR  (3)
#define TIMER0_CLOCK_COUNT      (0xff - 50)

void usart_init();
void timer0_init();
void serial_send_ln(const char *);
void usart_send(uint8_t *, uint8_t);
void usart_send_ln(uint32_t num);

SimpleClass.h

#pragma once

typedef unsigned char uint8_t;

#ifndef rxBufferLen
#define rxBufferLen 30
#endif
#ifndef txBufferLen
#define txBufferLen 30
#endif

class SimpleClass{
    uint8_t rxbuffer[rxBufferLen]; ///< receiver buffer
    uint8_t txBuffer[txBufferLen]; ///< transmitter buffer
    uint8_t rxbuff_index, ///< rxbuffer index. Indicates where to put new data
    txbuff_index; ///< txBuffer index. Indicates where to put new data
    public:
    void (*transmitter)(uint8_t * txbuff, uint8_t len);
    void pushtx(uint8_t byte);
    void pushrx(uint8_t byte);
    void flush();
    void foo();
};

SimpleClass.cpp

#include "simpleClass.h"

void SimpleClass::flush(){
    transmitter(txBuffer, txbuff_index);
}

void SimpleClass::pushtx(uint8_t byte){
    txBuffer[txbuff_index++] = byte;
}

void SimpleClass::pushrx(uint8_t byte){
    rxbuffer[rxbuff_index++] = byte;
}

void SimpleClass::foo(){
    uint8_t dv = 0;
    dv ++ ;
    pushtx(0x01);
    pushtx(0x02);
    pushtx(0x03);
    pushtx(0x04);
    pushtx(0x05);
    flush();
}

CPPFile1.cpp

#include "IncFile1.h"


    void usart_init(){
        unsigned int ubrr = 51;
        /*Set baud rate */
        UBRR0H = (unsigned char)(ubrr>>8);
        UBRR0L = (unsigned char)ubrr;
        /*Enable receiver and transmitter */
        UCSR0B = (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
        /* Set frame format: 8data, stop bit */
        UCSR0C = (3<<UCSZ00);
    }
    
    void timer0_init(){
        TCCR0B = TIMER0_CLOCK_PRESCALAR;
        TIMSK0 = 1; // enable timer overflow interrupt
        TCNT0 = TIMER0_CLOCK_COUNT;
    }
    
    void serial_send(const char * c){
        for(uint8_t i=0 ; c[i] != '\0';i++){
            while(!(UCSR0A & (1<<UDRE0)));
            UDR0 = c[i];
        }
        while(!(UCSR0A & (1<<UDRE0)));
        UDR0 = 0x0a;
        while(!(UCSR0A & (1<<UDRE0)));
        UDR0 = 0x0d;
    }
    
    void usart_send(uint8_t *buff, uint8_t len){
        for(uint8_t i = 0; i < len; i++){
            while(!(UCSR0A & (1<<UDRE0)));
            UDR0 = buff[i];
        }
    }
    
    void usart_send_ln(uint32_t num){
        for(uint8_t i =0;i < 4; i++){
            while(!(UCSR0A & (1<<UDRE0)));
            UDR0 = num >> (8*(3-i));
        }
    }

Edits

Quimby

You are violating the One Definition Rule - linking C++ program where the same class is defined twice and these definitions are not identical is undefined behaviour. The compiler/linker is not required to check or report these errors.

You are doing just that:

  • CPPFile1.cpp includes IncFile1.h which creates SimpleClass definition with buffers[50],
  • SimpleClass.cpp includes SimpleClass.h with buffers[30].

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

function pointer member variable

Function pointer to class template member

Why does taking a member function pointer value requires class name qualification even from inside of the class?

Why does the CreateWindow() function want the WindowClass's name member and not a pointer to the class itself?

Template parameter accepting pointer to class member function

Storing member function pointer from arbitrary class as class instance variable

Type conversion error in pointer to class member function

Why cannot reach derived class's member function using a base class pointer in C++? What's the design idea of it?

Does member variable still in the buffer when recursion function gets call?

variable no of arguments for class template's member function

how to pass pointer to member function of a template class?

Receiving an Error While Defining a Class Member Function

Declare and use a pointer to member function in another class

Function as a member "variable" in class

cast a pointer to member function in derived class to a pointer to abstract member function

pointer to a member function of a class

Class function not changing member variable

Member function pointer on derived class

Pointer to class member function

Return a function pointer from a class member function

C++ function pointer to class member

Why doesnt vector support size as member variable like length variable in a Java class, instead a function size()?

Why can't I assign a value to the class member variable in a bool function that returns const? C++

Defining a proxy for a member function that takes a member function pointer as a template argument

Pointer to Member Function Class Type

Pointer to member function of instance instead of class

Difficulty in passing function pointer of a class member function

Function pointer inside class point to that class's member function

Why does invoking a function with a pointer to one member variable inhibit optimization of other member variable?