繁体   English   中英

C中的内存访问冲突

[英]Memory access violation in 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

仍应创建已定义的字段,但控制台中不应显示空字段/地址

您的代码有一些问题。

  1. entrys成员是指向char的指针,该char永远不会初始化或接收动态分配的内存。 您已经静态声明了其他3个成员,并使用strcpy初始化了它们的值。 但是,不应在未分配的指针上使用strcpy ,因为您可能正在写入分配给程序运行的内存之外的任意内存空间。 内存访问冲突 #1。

  2. 您可以根据用户输入分配Periodictable 因此,如果用户输入的数字小于89,则当您引用Periodictable[88]时,您将尝试访问另一个可能超出程序范围的内存空间。 从一开始就知道元素的数量,您可以使用一个简单的固定数组,该数组将容纳所有118个元素(如果要按元素编号保留数组索引而忽略元素0,则大小为119)。 内存访问冲突 #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

最后,这些更改将使当前的设计工作正常进行,但是根据您要查找的内容,可能有更简单的方法来设计相同的程序。 尽管如此,我希望答案能解释发生了什么。

暂无
暂无

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

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