简体   繁体   English

C中的内存访问冲突

[英]Memory access violation in C

I've created a periodic table program in C, with an dynamic field, or at least I tried. 我已经用C创建了一个带有动态字段的元素周期表程序,或者至少我尝试过。

I will extend the program later, with the other 116 elements, but for now, it will be like this. 稍后,我将使用其他116个元素来扩展程序,但现在,它会像这样。

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. entrys成员是指向char的指针,该char永远不会初始化或接收动态分配的内存。 You have declared the other 3 members statically and initialized their values using strcpy . 您已经静态声明了其他3个成员,并使用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. 但是,不应在未分配的指针上使用strcpy ,因为您可能正在写入分配给程序运行的内存之外的任意内存空间。 Memory access violation #1. 内存访问冲突 #1。

  2. You allocate Periodictable based on the user input. 您可以根据用户输入分配Periodictable 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] . 因此,如果用户输入的数字小于89,则当您引用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). 从一开始就知道元素的数量,您可以使用一个简单的固定数组,该数组将容纳所有118个元素(如果要按元素编号保留数组索引而忽略元素0,则大小为119)。 Memory access violation #2. 内存访问冲突 #2。

  3. When you allocate the Periodictable array, you have forgotten to initialize it. 分配Periodictable数组时,您忘记了对其进行初始化。 Do remember that C does not initialize arrays by default, so you must do it yourself. 请记住,C默认情况下不会初始化数组,因此您必须自己进行初始化。 A call to memset() over the whole array would do. 在整个数组上调用memset()

  4. The if (Periodictable[i].entrys) will not work as you are not dereferencing the entrys pointer from your original implementation. if (Periodictable[i].entrys)将不起作用,因为您没有从原始实现中取消引用entrys指针。 If you decided to keep entrys as a pointer, you could write if (*Periodictable[i].entrys) instead. 如果决定保留entrys作为指针,则可以编写if (*Periodictable[i].entrys) 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). 但是,似乎并不一定需要使用指针,而是可以使用简单的char来解决问题(实际上, bool甚至更合适,更易读)。

  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. 您必须使用else i++语句跳过一个元素,因为该数组中没有足够的元素注册,所以它尚未显示。 You don't have to increase i again as the for loop already does that. 您不必再次增加i ,因为for循环已经做到了。

  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. 尽管如此,我希望答案能解释发生了什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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