C: арифметика указателя c и малло c () - НЕТ GO? - PullRequest
0 голосов
/ 09 апреля 2020

Знакомясь с указателями, я натолкнулся на раздел динамического распределения памяти c с использованием mallo c () и free (). Я хотел бы получить подтверждение или исправление моего понимания этой топи c.

До сих пор я понимал, что большие преимущества указателей могут быть двоякими:

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

Говоря о mallo c (), я чувствую, что арифметика указателей c может стать вполне опасно, если адрес указателя не сбрасывается. Учитывая приведенный ниже пример, я создал два указателя ptr и ptr1, используя mallo c (). Я понимаю, что две функции mallo c () выделяют два блока памяти, каждый размером с размер * sizeof (int), так что это зарезервированная память, а адреса первых элементов этих двух блоков передаются в ptr и ptr1 .

Используя первое для l oop, я присваиваю значения в ячейки памяти с помощью указателей. ptr использует арифметику указателя c, ptr1 использует арифметику массива c (если можно так назвать).

В конце для l oop, ptr не указывает на адрес первый элемент зарезервированного блока памяти и должен быть сброшен обратно, чтобы указывать на адрес первого элемента.

Второй для l oop печатает данные в двух блоках памяти. Там я не сбрасываю ptr, чтобы он указывал на адрес первого элемента в памяти.

Теперь большой вопрос: используя free (ptr), free () получает указатель, который указывает на определенный адрес ( кроме начального адреса блока памяти, который был зарезервирован). Правильно ли я понимаю, что при свободной записи (ptr) я теперь освобождаю другой блок памяти размером * sizeof (int) и могу выпустить некоторые конфиденциальные данные, которые не должны быть освобождены?

Это правильно понято? Если да, то желательно ли всегда использовать массив arithmeti c при использовании указателя в сочетании с mallo c ()?

Спасибо, Алекс

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

int main()
{
int size = 0;
printf("Enter the array size: ");
scanf("%d",&size);

int * ptr = (int *)malloc(size*sizeof(int));
int * ptr1 = (int *)malloc(size*sizeof(int));

int i = 0;
// First for loop
for( ; i<size;i++)
{
    *ptr = i;
    ++ptr;
    *(&ptr1[i]) = i;
}

ptr = ptr-size; // Resetting to the start address

// Second for loop
for(i = 0; i<size;i++)
{
    printf("%d\t\t",*ptr);
    ptr++;
    printf("%d\n",*(&ptr1[i]));
}

free(ptr);  // Is the correct memory block now freed?
free(ptr1);
return 0;
}

Ответы [ 2 ]

2 голосов
/ 09 апреля 2020

Ваша программа имеет неопределенное поведение. Значение указателя, переданное в free(), должно быть в точности равным значению, полученному из malloc(), calloc() или realloc(). From cppreference.com :

Поведение не определено, если значение ptr не равно значению, возвращенному ранее mallo c (), callo c () , reallo c () или align_allo c () (начиная с C11).

Поэтому сохраняйте неизменный указатель на ваше выделение для передачи на free() и используйте копию для арифметика указателя c.

0 голосов
/ 09 апреля 2020

Для начала в этих операторах используются избыточные операторы

*(&ptr1[i]) = i;

и

printf("%d\n",*(&ptr1[i]));

Они эквивалентны

ptr1[i] = i;

и

printf("%d\n", ptr1[i] );

Если указатель имеет значение, которое отличается от значения, возвращаемого вызовом mallo c, то вызов free для такого указателя приводит к неопределенному поведению.

Обратите внимание, что в этом l oop

for( ; i<size;i++)
{
    *ptr = i;
    ++ptr;
    *(&ptr1[i]) = i;
}

вы можете явно использовать арифметику указателя c для указателя ptr, например

for( ; i<size;i++)
{
    *( ptr + i ) = i;
    *(&ptr1[i]) = i;
}

In в этом случае значение самого указателя ptr не будет изменено.

...