Каков разум, которым код C с указателями, которые оно функционирует без проблем в linux, имеет проблемы в MAC?

В следующем примере оно является осуществлением динамических arrays в C используя malloc и realloc. Когда этот код составлен в Линукс (C11), нет никакой проблемы функционирует, но если тот же код работает в MAC (Xcode в macbook Пилит, чтобы быть более точными), они начинают проблемы, программа составляет но в работать появляется ошибка в линии, которую делает realloc показывая, что не имеется разрешение, чтобы соглашаться на эту ячейку запоминающего устройства.

    #include <stdio.h>
    #include <stdlib.h>

    #define TRUE 1;
    #define FALSE 0;


    struct dynarray {
        int * data;
        int capacity;
        int size;
    };

    struct dynarray array1;


    int daInit(struct dynarray * dynArrayPtr,int capacity){
        int * arrayDataAddress = (int *)malloc(capacity * sizeof(int));
        if (arrayDataAddress != NULL){
            dynArrayPtr->data = arrayDataAddress;
            dynArrayPtr->capacity = capacity;
            dynArrayPtr->size = 0;
            return TRUE;
        }else{
            return FALSE;
        }
    }

    int daPushBack(struct dynarray * dynArrayPtr, int value){
        if (dynArrayPtr->size == dynArrayPtr->capacity){
            dynArrayPtr->capacity *= 2;
            dynArrayPtr->data = (int *)realloc(dynArrayPtr->data,dynArrayPtr->capacity * sizeof(int)); 
            if (dynArrayPtr->data == NULL){
                return FALSE;
            }
        }
        *(dynArrayPtr->data + dynArrayPtr->size * sizeof(int)) = value;
        dynArrayPtr->size++;
        return TRUE;
    }


    int daIntGet(struct dynarray * dynArrayPtr, int position){
        int* elementPos = (int *) dynArrayPtr->data + sizeof(int) * position;
        return *elementPos;
    }



    int main(int argc, char** argv) {
        daInit(&array1,5);
        printf("%p\n", array1.data);
        for (int i=0; i<10;i++){
            if (!daPushBack(&array1,i)) exit(0);
        }

        for (int i=0; i<array1.size; i++){
            printf("%i\n", daIntGet(&array1,i));
        }

        return (EXIT_SUCCESS);
    }
1
задан 08.01.2017, 18:35
0 ответов

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

В C, арифметика с указателями принимает во внимание размер остроконечного объекта. А именно, ввиду того, что dynArrayPtr->data укажи на один int, вычисление dynArrayPtr->data + i укажи на элемент i с перемещением i * sizeof(int) байт. Как следствие,

*(dynArrayPtr->data + dynArrayPtr->size * sizeof(int)) = value;

смоги изменять в память вне безрассудной памяти. Выражение data + size укажи на байт data + size*sizeof(size), так вступите в брак data + size*sizeof(size) обозначься в data + size*sizeof(size)*sizeof(size). Ты используешь то же выражение, спутанное в daIntGet, так что ты читаешь то же расположение, которое ты написал, но это чужая память, которая может быть занятой другой структурой или может быть не представляйте в карте памяти (чем ты получаешь segfault в Mac).

В конце концов, ты был бы должен помещать

*(dynArrayPtr->data + dynArrayPtr->size) = value;

но моего суждения, яснее будьте

dynArrayPtr->data[dynArrayPtr->size] = value;

у которого есть точно та же семантика.

2
ответ дан 03.12.2019, 17:50
  • 1
    Превосходный ответ. Почти конечно, что оно функционирует в Linux из-за различной implementació n realloc( ) и granularidad mí nima блоков memó смейтесь размещенные, что hará не удаваться в зависимости от tamañ или array. Тема, aritmé костариканская указателей, я продолжаюсь , для которых они начинаются. –  08.01.2017, 20:22