Bus error while initializing a member array of a struct

Shawn-B Z

New Member
Joined
May 6, 2023
Messages
2
Reaction score
0
Credits
8
Hi experts,

Currently I'm facing a problem that bus error occurs while initializing a member array of a struct, the struct is pointed to a mapped shared memory(mapped by mmap()).
Below is my test application code, the bus error occurs while memset data in the init() function. The shared memory is reserved for application use. It looks weird that the test code is quite simple, could this be a system configuration problem?

C:
#define appAlign(value, align)   ((( (value) + ( (align) - 1 ) ) / (align) ) * (align) )
#define appFloor(value, align)   (( (value) / (align) ) * (align) )

#define LOGGER_REC_BUFS_MEM_ADDR  0xB9600000UL
#define LOGGER_REC_BUFS_MEM_SIZE  0x00200000
#define ONE_REC_MAX_SIZE 0x0080000

struct LoggerRecord
{
    uint8_t data[ONE_REC_MAX_SIZE];
    void (*init)(uint8_t *data);
};

void init(uint8_t *data)
{
    printf("Start Memset occured at 0x%p\n", data);
    memset(data, 0, ONE_REC_MAX_SIZE);
    printf("Memset occured at 0x%p\n", data);
};

/*
 *  Map physical address to virtual address
 */
void *phyToVirtMap(void *physAddr, uint32_t size) {
    int32_t     status      = 0;
    uint32_t    pageSize    = getpagesize();
    void        *virtAddr   = NULL;
    static int  devMemFd    = -1;
    uintptr_t   taddr;
    uint32_t    tsize;

    if(devMemFd == -1) {

        devMemFd = open("/dev/mem",O_RDWR|O_SYNC);
        if(devMemFd  < 0) {
            status = -1;
        }

        printf("Allocated\n");
    }

    if((0 == status) && (0 <= devMemFd)) {

        taddr = (uintptr_t)physAddr;
        tsize = size;

        tsize = appAlign(tsize + (taddr % pageSize), pageSize);
        taddr = appFloor(taddr, pageSize);

        printf("Before mmap\n");
        virtAddr    = mmap(
                        0,
                        tsize,
                        (PROT_READ | PROT_WRITE),
                        (MAP_SHARED),
                        devMemFd,
                        taddr);
        printf("After mmap\n");

        if(MAP_FAILED == virtAddr) {

            virtAddr = NULL;
            perror("Error: ");
            printf("mmap failed\n");
        }
        else {
            virtAddr = (void*)((uintptr_t)virtAddr + ((uintptr_t)physAddr % pageSize));
        }
    }

    return virtAddr;
}

int main()
{
    int status = 0;
    uint8_t* recBufsBase = (uint8_t*)phyToVirtMap((void*)LOGGER_REC_BUFS_MEM_ADDR, LOGGER_REC_BUFS_MEM_SIZE);

    if(recBufsBase == NULL)
    {
        printf("Virtual Address is NULL\n");
    }
    else
    {
        printf("Virt Addr = 0x%p\n",recBufsBase);
    }

    struct LoggerRecord *ptr = (struct LoggerRecord *) recBufsBase;
    ptr->init = init;
    ptr->init(ptr->data);

    return status;

}
 
Last edited:


I haven’t had time to look through all of your code yet. But a bus error usually means that you’re attempting to access memory that doesn’t exist, or that exceeds the usable memory.

Or it could be that the memory address doesn’t have the appropriate alignment for use with one of the data-types, or cpu instructions in your compiled code. So it’s the wrong type of memory address for that operation/data. This can be a problem if you’re using casting a lot, to cast data from one type to another inside the mapped memory. That can cause things to go out of alignment and cause the SIGBUS error to be sent to your application.

There are a few other things that could be causing it - running out of memory/not enough physical memory to map to the virtual memory. /var/cache running out of space, the page file being inaccessible etc.

Rather than list all of the possibilities, I’ll direct you to this thread, which might help you:
It covers a lot of situations that can cause a bus error.

If I get time, I’ll grab a copy of your code and will compile it and run it through gdb, to see if I can work out where you’re going wrong. In the meantime, if you (or one of the admins/mods here) could edit your post, to put your code into [code][/code] tags, it would make it a little bit easier to digest.
 
From the provided code, it seems that there might be some issues with the memory mapping and/or alignment. A bus error often occurs when the program tries to access memory that it doesn't have permission to access, or when the address is not aligned correctly. In your code, there are a few places where things could potentially go wrong.
  1. Alignment and page size: Make sure the values you are using for the alignment and page size are correct for your system. You might also want to verify the memory region you are trying to access (LOGGER_REC_BUFS_MEM_ADDR and LOGGER_REC_BUFS_MEM_SIZE).
  2. mmap() call: Ensure that the mmap() call is working correctly and returning a valid address. Check if the perror() function outputs any error messages.
  3. Accessing struct members: In the main() function, after mapping the memory, you are directly casting the virtual address to a struct pointer. This assumes that the memory is already aligned correctly for the struct. If it is not, you might encounter a bus error. In this case, you should make sure the memory is correctly aligned before accessing the struct members.
To identify the root cause of the issue, you can do the following:
  1. Check the alignment and page size values.
  2. Print the virtual address returned by mmap() and ensure it is not NULL or MAP_FAILED.
  3. Print the address of the struct members before accessing them to ensure they are correctly aligned.
Additionally, you might want to consider using the posix_memalign() function to allocate aligned memory instead of manually handling alignment with macros. This could help avoid potential alignment issues.
 
I thought this could be a alignment problem, but after print the address of the data that is going to be initialized, I find the address is aligned, please check the test log below. The test code is running on a Cortex-A72 64-bit core with Linux 5.10.120. I also print the pageSize and the ailgned memory start address and size before mmap(), it looks fine to me.

The returned virtual memory address is not NULL and no error reports. The memory section I'm trying to map is part of our 4GB DDR address space, I think the memory section is valid.

test log:
test log.png
 
Last edited:


Top