C中的内存访问冲突

时间:2017-02-05 21:21:03

标签: c runtime-error memory-access

我在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 个答案:

答案 0 :(得分:0)

您的代码有一些问题。

  1. entrys成员是指向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甚至更合适,更清晰)。

    < / li>
  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

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