简体   繁体   中英

Memory access violation in C

I've created a periodic table program in C, with an dynamic field, or at least I tried.

I will extend the program later, with the other 116 elements, but for now, it will be like this.

Compiler says nothing, but I get a runtime error: 'memory access violation'

What did I overlooked/miss?

The Output should only show the saved elements (Aluminium/Radium).

#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);
}

output should be like this:

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

The defined field should still be created, but the empty fields/adresses should not be shown in the console

There are a few problems with your code.

  1. The entrys member is a pointer to char which never gets initialized or receives dynamically allocated memory. You have declared the other 3 members statically and initialized their values using strcpy . However, strcpy should not be used on unallocated pointers, as you could be writing to an arbitrary memory space outside the memory allocated for your program to run. Memory access violation #1.

  2. You allocate Periodictable based on the user input. So, if the user inputs a number smaller than 89, you would be trying to access another memory space that could be out of bounds for your program when you reference Periodictable[88] . As you know the number of elements from the start, you could use a simple fixed array that would hold all 118 elements (thus of size 119 if you want to keep the array index by element number and ignore element 0). Memory access violation #2.

  3. When you allocate the Periodictable array, you have forgotten to initialize it. Do remember that C does not initialize arrays by default, so you must do it yourself. A call to memset() over the whole array would do.

  4. The if (Periodictable[i].entrys) will not work as you are not dereferencing the entrys pointer from your original implementation. If you decided to keep entrys as a pointer, you could write if (*Periodictable[i].entrys) instead. However, it doesn't seem to be necessary to use a pointer, instead a simple char could do the trick (actually a bool would even be more appropriate and more legible).

  5. You are necessarily skipping an element with the else i++ statement, it just didn't show yet because there are not enough elements registered in the array. You don't have to increase i again as the for loop already does that.

  6. There are two styles of initialization in your code, and both could be made to work. One is to write values directly to the array, the other is to declare elements on the stack, write to them, and copy them to the array. In the code below the two elements are initialized differently as an example.

So, that's what the code would look like.

#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);
}

And it outputs:

Recorded elements:

Name: Aluminium
Symbol: Al
Atomic number: 13

Name: Radium
Symbol: Ra
Atomic number: 88

Finally, these changes would make the current design work, but there are probably easier ways to design the same program depending on what you are looking for. Nonetheless I hope the answer helps explain what was going on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM