Нарушение доступа к памяти в C

Я создал программу для периодических таблиц в C, с динамическим полем, или, по крайней мере, я пытался.

Я расширю программу позже, с другими 116 элементами, но пока, это будет так.

Компилятор ничего не говорит, но я получаю ошибку времени выполнения: "нарушение доступа к памяти"

Что я упустил / пропустил?

Выходные данные должны отображать только сохраненные элементы (алюминий / радий).

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


  typedef struct
  {
    char Name[20];
    char Symbol[3];
    char Atomicnumber[5];
    char* entrys;
  } Element;


int main(void)
{
    //Define the two entrys/elements

    Element Aluminium;
    strcpy(Aluminium.Name, "Aluminium");
    strcpy(Aluminium.Symbol, "Al");
    strcpy(Aluminium.Atomicnumber, "13");

    Element Radium;
    strcpy(Radium.Name, "Radium");
    strcpy(Radium.Symbol, "Ra");
    strcpy(Radium.Atomicnumber, "88");

    int size=0;
    //Define field
    printf ("size of field:");
    scanf( "%d" , &size);
    //Gives the saved Elements an Adress in Array/Field  

    Element Periodictable [size];

    strcpy(Periodictable[13].Name, "Aluminium");
    strcpy(Periodictable[13].Symbol, "Al");
    strcpy(Periodictable[13].Atomicnumber, "13");
    strcpy(Periodictable[13].entrys, "1");

    strcpy(Periodictable[88].Name, "Radium");
    strcpy(Periodictable[88].Symbol, "Ra");
    strcpy(Periodictable[88].Atomicnumber, "88");
    strcpy(Periodictable[88].entrys, "1");

    void output(Element* Periodictable, int*entry);

    printf("Recorded elements:\n");
    printf("\n");
    for (int i=1; i<= size; i++)
    {
        if (Periodictable[i].entrys)
        {
            printf("Name: %s \n",Periodictable[i].Name);
            printf("Symbol: %s \n",Periodictable[i].Symbol);
            printf("Atomic number: %s \n",Periodictable[i].Atomicnumber);
            printf("\n");
        }
        else i++;
    }

    return (0);
}

вывод должен быть таким:

Recorded elements:
Name: Aluminium
Symbol: Al
Atomic number: 13
Name: Radium
Symbol: Ra
Atomic number: 88

Определенное поле все еще должно быть создано, но пустые поля / адреса не должны отображаться в консоли

0 ответов

Есть несколько проблем с вашим кодом.

  1. entrys член является указателем на char который никогда не инициализируется или не получает динамически выделенную память. Вы объявили 3 других члена статически и инициализировали их значения, используя strcpy, Тем не мение, strcpy не следует использовать для нераспределенных указателей, так как вы можете записывать в произвольное пространство памяти вне памяти, выделенной для вашей программы для запуска. Нарушение доступа к памяти #1.

  2. Вы выделяете Periodictable на основе пользовательского ввода. Таким образом, если пользователь вводит число меньше 89, вы пытаетесь получить доступ к другому пространству памяти, которое может выходить за пределы вашей программы, когда вы ссылаетесь Periodictable[88], Поскольку вы знаете количество элементов с самого начала, вы можете использовать простой фиксированный массив, который будет содержать все 118 элементов (например, размером 119, если вы хотите сохранить индекс массива по номеру элемента и игнорировать элемент 0). Нарушение доступа к памяти № 2.

  3. Когда вы выделяете Periodictable массив, вы забыли его инициализировать. Помните, что C не инициализирует массивы по умолчанию, поэтому вы должны сделать это самостоятельно. Вызов memset() по всему массиву будет делать.

  4. if (Periodictable[i].entrys) не будет работать, так как вы не разыменовываете entrys указатель из вашей оригинальной реализации. Если вы решили сохранить entrys в качестве указателя вы могли бы написать if (*Periodictable[i].entrys) вместо. Тем не менее, нет необходимости использовать указатель, а просто char мог бы добиться цели (на самом деле bool было бы даже более уместно и более разборчиво).

  5. Вы обязательно пропускаете элемент с else i++ Это просто не показывалось, потому что в массиве недостаточно элементов. Вам не нужно увеличивать i снова, поскольку цикл for уже делает это.

  6. В вашем коде есть два стиля инициализации, и оба можно заставить работать. Один - записывать значения непосредственно в массив, другой - объявлять элементы в стеке, записывать их и копировать в массив. В приведенном ниже коде два элемента инициализируются по-разному в качестве примера.

Вот так будет выглядеть код.

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

#define MAXSIZE 119

typedef struct
  {
    char Name[20];
    char Symbol[3];
    char Atomicnumber[5];
    char entrys;
  } Element;


int main(void)
{
    Element Periodictable [MAXSIZE];
    memset(&Periodictable, 0, sizeof(Element) * MAXSIZE);

    Element Aluminium;
    strcpy(Aluminium.Name, "Aluminium");
    strcpy(Aluminium.Symbol, "Al");
    strcpy(Aluminium.Atomicnumber, "13");
    Aluminium.entrys = 1;
    memcpy(&Periodictable[13], &Aluminium, sizeof(Element));

    strcpy(Periodictable[88].Name, "Radium");
    strcpy(Periodictable[88].Symbol, "Ra");
    strcpy(Periodictable[88].Atomicnumber, "88");
    Periodictable[88].entrys = 1;

    printf("Recorded elements:\n");
    printf("\n");
    for (int i=1; i<= MAXSIZE; i++)
    {
        if (Periodictable[i].entrys)
        {
            printf("Name: %s \n",Periodictable[i].Name);
            printf("Symbol: %s \n",Periodictable[i].Symbol);
            printf("Atomic number: %s \n",Periodictable[i].Atomicnumber);
            printf("\n");
        }
    }

    return (0);
}

И это выводит:

Recorded elements:

Name: Aluminium
Symbol: Al
Atomic number: 13

Name: Radium
Symbol: Ra
Atomic number: 88

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

Другие вопросы по тегам