Исключение: нарушение доступа - PullRequest
0 голосов
/ 23 февраля 2020

Эта функция переворачивает массив указателей и возвращает его основному. Основная проблема заключается в том, что код возвращает выданное исключение: нарушение прав чтения. fptr было 0x CCCCCCCC.

Minimal Description

Что может быть источником ошибки?

int* mirror(int* p[], int n) {
    int* ptr,* fptr;
    int swap;
    ptr = p[0];
    fptr = p[n-1];
    while (fptr > ptr) {
        swap = *ptr;
        *ptr = *fptr;
        *fptr = swap;
        ptr++;
        fptr--;
    }
    return *p;
}

Ответы [ 4 ]

1 голос
/ 23 февраля 2020

Это проблема:

while (fptr > ptr) { ... }

ptr - это первые элементы (первый указатель), а fptr - последний элемент (последний указатель), и вы проходите через массив, в то время как первый элемент меньше, чем последний элемент, но это означает, что элементы в массиве вставляются в порядке адреса, который, я считаю, не ..

Вместо этого вы должны использовать измерение (n) для этого:

int** mirror(int* p[], int n) { // return a pointer to integers pointer, not a pointer to integer
    for(int i = 0; i < n/2 ; i++){ // go through the first half of the array
       int* tmp = p[i];  // and those three lines swap the current and the n - current elements
       p[i] = p[n-i-1];
       p[n] = tmp;
    }
    return p;
}
0 голосов
/ 23 февраля 2020

Проблема в том, что вы использовали неправильные типы. Правильная версия будет выглядеть следующим образом:

    int **ptr, **fptr;
    int* swap;
    ptr = &p[0];
    fptr = &p[n - 1];

С этими изменениями ваша функция работает как положено, хотя то, что она возвращает, непригодно для большинства целей. Либо верните p (int**), либо сделайте его void.

void mirror(int* p[], int n) {
    if(n > 0) {                  // check this or you risk undefined behavior
        int** ptr = &p[0];
        int** fptr = &p[n-1];
        int* swap;
        while(ptr < fptr) {
            swap = *ptr;
            *ptr = *fptr;
            *fptr = swap;
            ptr++;
            fptr--;
        }
    }
}

Обратите внимание, что уже существует стандартная утилита для обмена двумя значениями, которая называется std::swap:

void mirror(int* p[], int n) {
    if(n > 0) {
        for(int **ptr = &p[0], **fptr = &p[n - 1]; ptr < fptr; ++ptr, --fptr) {
            std::swap(*ptr, *fptr);
        }
    }
}

Как последнее замечание, есть также стандартная утилита для обращения значений в контейнере под названием std::reverse, которая выполняет то же, что и ваша функция mirror.

Вместо

mirror(arr, std::size(arr));

до

std::reverse(std::begin(arr), std::end(arr));
0 голосов
/ 23 февраля 2020

попробуйте переместить ваш массив следующим образом:

void mirror(int* p, int n){
  int* ptr,* fptr;
  int swap;
  ptr = p;
  fptr = p+n-1;
  while (fptr != ptr) {
    swap = *ptr;
    *ptr = *fptr;
    *fptr = swap;
    ptr++;
    fptr--;
  }
}
0 голосов
/ 23 февраля 2020

Для начала тип возврата int * функции не имеет смысла.

int* mirror(int* p[], int n) {

Лучше объявить функцию как имеющую тип возврата void.

Если у вас есть массив указателей типа int *, то указатель на его элементы имеет тип int **.

Кроме того, пользователь может передать 0 в качестве второго аргумента. Вам следует проверить этот случай.

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

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

Функция может быть определена как

void mirror( int * p[], size_t n ) 
{
    if ( n != 0 )
    {
        for ( int **first = p, **last = p + n; first < --last; ++first )
        {
            int tmp = **first;
            **first = **last;
            **last = tmp;
        }
    }
}

Вот демонстрационная программа

#include <iostream>

void mirror( int * p[], size_t n ) 
{
    if ( n != 0 )
    {
        for ( int **first = p, **last = p + n; first < --last; ++first )
        {
            int tmp = **first;
            **first = **last;
            **last = tmp;
        }
    }
}

int main() 
{
    const size_t N = 5;
    int a[N] = { 10, 30, 30, 40, 50 };
    int * b[N] = { a, a + 1, a + 2, a + 3, a + 4 };

    for ( const auto &item : a )
    {
        std::cout << item << ' ';
    }
    std::cout << '\n';

    mirror( b, N );

    for ( const auto &item : a )
    {
        std::cout << item << ' ';
    }
    std::cout << '\n';

    return 0;
}

Выход программы:

10 30 30 40 50 
50 40 30 30 10

Обратите внимание, что вместо замены элементов «вручную» вы можете использовать стандартную функцию std::swap.

...