Нарушение доступа к памяти в 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 ответов
Есть несколько проблем с вашим кодом.
entrys
член является указателем наchar
который никогда не инициализируется или не получает динамически выделенную память. Вы объявили 3 других члена статически и инициализировали их значения, используяstrcpy
, Тем не мение,strcpy
не следует использовать для нераспределенных указателей, так как вы можете записывать в произвольное пространство памяти вне памяти, выделенной для вашей программы для запуска. Нарушение доступа к памяти #1.Вы выделяете
Periodictable
на основе пользовательского ввода. Таким образом, если пользователь вводит число меньше 89, вы пытаетесь получить доступ к другому пространству памяти, которое может выходить за пределы вашей программы, когда вы ссылаетесьPeriodictable[88]
, Поскольку вы знаете количество элементов с самого начала, вы можете использовать простой фиксированный массив, который будет содержать все 118 элементов (например, размером 119, если вы хотите сохранить индекс массива по номеру элемента и игнорировать элемент 0). Нарушение доступа к памяти № 2.Когда вы выделяете
Periodictable
массив, вы забыли его инициализировать. Помните, что C не инициализирует массивы по умолчанию, поэтому вы должны сделать это самостоятельно. Вызовmemset()
по всему массиву будет делать.if (Periodictable[i].entrys)
не будет работать, так как вы не разыменовываетеentrys
указатель из вашей оригинальной реализации. Если вы решили сохранитьentrys
в качестве указателя вы могли бы написатьif (*Periodictable[i].entrys)
вместо. Тем не менее, нет необходимости использовать указатель, а простоchar
мог бы добиться цели (на самом делеbool
было бы даже более уместно и более разборчиво).Вы обязательно пропускаете элемент с
else i++
Это просто не показывалось, потому что в массиве недостаточно элементов. Вам не нужно увеличиватьi
снова, поскольку цикл for уже делает это.В вашем коде есть два стиля инициализации, и оба можно заставить работать. Один - записывать значения непосредственно в массив, другой - объявлять элементы в стеке, записывать их и копировать в массив. В приведенном ниже коде два элемента инициализируются по-разному в качестве примера.
Вот так будет выглядеть код.
#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
Наконец, эти изменения позволят сделать текущий дизайн работ, но, возможно, существуют более простые способы разработки одной и той же программы в зависимости от того, что вы ищете. Тем не менее, я надеюсь, что ответ поможет объяснить, что происходило.