Получение предупреждений «вне границ» и «неинициализированная переменная» с отображенной общей памятью - PullRequest
0 голосов
/ 21 ноября 2018

Как часть моего приложения на C для Linux, я написал небольшую библиотеку, позволяющую различным процессам обмениваться данными через общие области памяти.

У меня много предупреждений для потенциальных указателей за пределами допустимого и потенциальнонеинициализированные переменные, содержащиеся в областях памяти, которые я создаю таким образом.

Рассмотрим функцию, которую я написал для создания области общей памяти:

int LayOutShm (const char *shm_key, size_t memory_size, void ** new_memory)
{
    int fd_value = 0;
    void * pshm = NULL;
    int return_value = MEM_MGMT_SHM_ERROR;

    /* Force new_buffer pointer to NULL just like we initialize return_value to MEM_MGMT_SHM_ERROR */
    *new_memory = NULL;

    /* Shared object is created with O_EXCL to prevent two namesake areas from being created*/
    fd_value = shm_open(shm_key, O_CREAT | O_RDWR | O_EXCL , S_IRWXU);

    if(fd_value > 0){
        if(ftruncate(fd_value, memory_size) == 0){
            /* Here is where we get the pointer to the created memory area */
            pshm = mmap(NULL, memory_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_value, 0);
            if(pshm != MAP_FAILED){
                return_value = MEM_MGMT_SHM_OK;
                memset(pshm,0,memory_size); /* Initialize the memory area */
                *new_memory = pshm; /* Pass the pointer back to the caller */
            }
        }
    }

    return return_value;
}/*LayOutShm*/

Теперь вот какой-то фрагмент кода, в котором я получаюпредупреждения:

#define SHM_KEY                 "my_shm_key"

typedef struct{
    pthread_mutex_t shm_mutex;
    int shm_var1;
    char shm_var2;
    union{
        int shm_union_var1;
        char shm_union_var2;
    }shm_union
}t_shm_area;

static t_shm_area * shm_area = NULL;

static int ShmInitialization(void)
{
    int return_value = -1;

    (void)LayOutShm(SHM_KEY, sizeof(t_shm_area), (void**)&shm_area);

    /*Check for errors in shared memory creation*/
    if (shm_area == NULL){
        syslog(LOG_ERR | LOG_USER, "Error laying out shared memory segment\n");
    }
    else{
        shm_area->var1 = 0; /* This assignment gets flagged with a potential out-of-bounds runtime error */
        shm_area->shm_union.shm_union_var2 = 0; /* This assignment gets flagged with a potential out-of-bounds runtime error */

        /*Create empty attributes structure*/
        pthread_mutexattr_t mutex_attributes;

        /*Initialize attributes structures with default values*/
        (void)pthread_mutexattr_init(&mutex_attributes);

        /*Set attributes structure with shared memory value*/
        (void)pthread_mutexattr_setpshared(&mutex_attributes, PTHREAD_PROCESS_SHARED);

        /*settype mutex PTHREAD_MUTEX_ERRORCHECK*/
        (void)pthread_mutexattr_settype(&mutex_attributes, PTHREAD_MUTEX_ERRORCHECK);

        /*Initialize the mutex with all the previous attributes*/
        (void)pthread_mutex_init(&shm_area->shm_mutex, &mutex_attributes);

        return_value = 0;
    }

    return return_value;
}/*ShmInitialization*/

Это первый раз, когда я пробую свои силы в двойных указателях, поэтому я не удивлюсь, если я испорчу что-либо с этим пробелом ** в декларации или способом, которым яприведите двойной указатель ввода к void.

Предыдущая реализация функции возвращала указатель напрямую и не создавала эти проблемы, но меня попросили изменить его, чтобы мы могли вернуть код состояния (даже еслимы их пока не используем).

После создания этой области любая локально объявленная переменная, которую я передаю в библиотеку дляЗначения из разделяемой памяти «испорчены» предупреждениями о возможных «недопустимых» ошибках времени выполнения или «переменная может быть не инициализирована».Библиотека уже была протестирована с несколькими различными типами структур данных (некоторые размером до 15 КБ), а целостность и производительность данных удовлетворительные.

Есть идеи, почему я получаю эти предупреждения?

Большое спасибо, с наилучшими пожеланиями!

1 Ответ

0 голосов
/ 21 ноября 2018

Общий тип указателя в C: void*.Однако не существует общего типа указатель на указатель void**.Таким образом, приведение (void**)&shm_area является приведением между несовместимыми типами указателей.Технически это неопределенное поведение (строгое нарушение псевдонимов), поэтому может произойти все что угодно.

Чтобы исправить это, используйте временную void* для передачи параметра:

void* vptr = shm_area;
LayOutShm(...&vptr); 
shm_area = vptr;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...