程序的错误输出,使用指向结构数组的指针

Posted

技术标签:

【中文标题】程序的错误输出,使用指向结构数组的指针【英文标题】:wrong output of programm, using pointers to an array of structs 【发布时间】:2021-09-23 21:00:45 【问题描述】:

我正在尝试运行模拟并将点创建为结构。我现在想将它们存储在一个数组中并尝试在该数组上使用一个指针。当我运行程序时,它只是随机给我一个错误的输出。我怀疑指针“Point *Point”或使用 malloc() 函数有问题。当我改变事情时它只会变得更糟,程序甚至没有完成并给我这个错误代码:进程返回-1073741819(0xC0000005)

如果有人知道它失败的原因,我会非常高兴:)

这是我的代码

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define M_PI 3.14159265

//mx..+bx.+kx=p*sgn(x.)

double p=1;
double m=1;
double const_b=1;
double const_k=1;

typedef struct point
    double counter;
    double x;
    double xDot;
Point;

double DGL(double x, double xDot)
    int sgn=0;
    if(xDot>0)
        sgn=1;
    
    else
        sgn=-1;
    
    double xDotDot = -const_b/m*xDot-const_k/m*x+p/m*sgn;
    return xDotDot;


Point *runSimulation(double time, double x_0, double step)

    double x=x_0;
    double xDot=0;
    double xDotDot=0;
    double counter=0;
    int i=0;

    Point *Point= malloc(time/step*sizeof(Point));

    while(counter<time)
    
        xDotDot=DGL(x, xDot);
        xDot=xDot+xDotDot*step;
        x=x+xDot*step;

        Point[i].x=x;
        Point[i].xDot=xDot;
        Point[i].counter=counter;

        counter = counter + step;
        i++;
    

    return Point;


void printSimulation(Point *Point, int length, FILE* datei)

    for(int i=0; i<length; i++)
    
        //fprintf(datei, "%.2f ; %.2f ; %.2f\n", Point[i].counter, Point[i].x, Point[i].xDot);
        printf("t=%.3f[s] ; x=%.3f[m] ; x_punkt=%.3f[m/s]\n", Point[i].counter, Point[i].x, Point[i].xDot);
    


int main()

    double x=0, xDot=0, xDotDot=0, x_0=0;
    double step=0.1, counter=0, time=2;
    double timeTol=0.05;
    double dauerT=0, lastCount=0;

    Point *PhasePtr;

    //Datei für Results öffnen
    FILE* datei = fopen("selbsterregte Schwingung_results.csv", "a");

    if(datei==NULL)
        printf("Fehler bei Dateizugriff");
        return 1;
    

    //Parameter eingeben
    printf("Simulationsparamter eingeben \nDämpfungsfaktor b:");
    scanf("%lf", &const_b);
    printf("Startauslenkung x,0=");
    scanf("%lf", &x_0);
    printf("Simulationsdauer I:");
    scanf("%lf", &time);
    fflush(stdin);
    int length=time/step;

    //Simulation läuft
    PhasePtr=runSimulation(time, x_0, step);

    //Ergebnisse auf Bildschirm und in Datei gespeichert
    printSimulation(PhasePtr, length, datei);

    fclose(datei);
    return 0;

这是错误的输出(很明显,长数字和中间的空值是错误的)

t=1.600[s] ; x=-0.502[m] ; x_punkt=-0.975[m/s]
t=1.700[s] ; x=-0.595[m] ; x_punkt=-0.928[m/s]
t=1.800[s] ; x=-0.682[m] ; x_punkt=-0.875[m/s]
t=1.900[s] ; x=-0.764[m] ; x_punkt=-0.820[m/s]
t=2.000[s] ; x=-0.840[m] ; x_punkt=-0.761[m/s]
t=2.100[s] ; x=-0.911[m] ; x_punkt=-0.701[m/s]
t=179538685518702200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000[s] ; x=0.000[m] ; x_punkt=11186857329615961000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=179538516283209850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000[s] ; x=195426269015847380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=0.000[s] ; x=0.000[m] ; x_punkt=0.000[m/s]
t=78973501660828132000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000[s] ; x=0.000[m] ; x_punkt=14621964126845871000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000[m/s]
t=3.900[s] ; x=-1.096[m] ; x_punkt=0.779[m/s]
t=4.000[s] ; x=-1.005[m] ; x_punkt=0.911[m/s]
t=4.100[s] ; x=-0.903[m] ; x_punkt=1.020[m/s]
t=4.200[s] ; x=-0.792[m] ; x_punkt=1.108[m/s]
t=4.300[s] ; x=-0.675[m] ; x_punkt=1.177[m/s]
t=4.400[s] ; x=-0.552[m] ; x_punkt=
and so on

【问题讨论】:

请显示一些你给程序的输入示例。顺便说一句,程序中有很多未使用的变量。在制作minimal reproducible example 时尝试将所有这些都去掉。 命名变量与类型相同很混乱。 请张贴一些 csv 文件。也许翻译一些提示 Point *Point= malloc(time/step*sizeof(Point));?!?!你知道sizeof(Point)使用的是哪个Point吗? @MikeCAT 说这很令人困惑,这是真的。但这也很可能是完全错误,因为使用了错误的Point。如果sizeof() 在这种情况下返回指针变量 Point 的大小,而不是结构类型Point。你知道吗?如果没有,请更改代码。如果您确实知道,无论如何都要更改代码,因为它很混乱。 【参考方案1】:

我可以在这段代码中看到大量可能导致此问题的问题:

    名称在不同上下文中到处重复:
如果您将结构命名为与类型相同的名称,您可能会混淆编译器(实际上也会混淆您自己)。当你键入 Point 时,它是指结构类型还是结构?这取决于编译器,它可能会感到困惑并使用错误的编译器。这不是代码中唯一的问题,但它是最严重的违规者
    我不清楚您要对代码进行哪些数学运算,编译器更不清楚:

double xDotDot = -const_b/mxDot-const_k/mx+p/m*sgn;

有了上面的语句,你想让编译器做(xDot*const_b)/m 吗?因为这就是它的评估方式
    带双打的 Malloc

Point* pnt = malloc(time / step * sizeof(Point));

确实不应该这样做。首先将其转换为正确的类型,即。 uint32_t 由于您没有明确确定类型,编译器可能会假设您正在使用 uint32_t 值进行数学运算,在这种情况下,0.1 将被转换为 0,并且您的等式将被解释为如下,这显然会导致问题使用您的程序:

Point* pnt = malloc(time/0* sizeof(Point));

    您不应该在函数中使用 malloc:
malloc 在 main 中分配指针数组的大小,将指向所述数组的指针传递到函数中。然后,您将不必处理返回结构指针的任何笨拙问题,这对 malloc 来说是未来的好习惯;您希望尽可能清楚地表明您已分配内存,因此您不会遇到代码继续分配内存直到处理器上没有剩余空间的情况

【讨论】:

谢谢!我做了这些更改,现在它可以正常工作了【参考方案2】:

至少有这些问题:

    Point *Point= malloc(time/step*sizeof(Point)); 是狡猾的,因为它可能由于分数截断而分配不足。

一般来说,最好使用整数数学来查找分配需求并使用它来迭代循环。

    Point *Point= malloc(time/step*sizeof(Point))浑水:那个大小是类型还是指针?为了清楚起见,使用不同的名称。

//                            Pass in length---v
Point *runSimulation(double time, double x_0, int length)

    double step = time/length;
    double x=x_0;
    double xDot=0;
    double xDotDot=0;
    double counter=0;
    int i=0;

    // Point *Point= malloc(length*sizeof(Point));
    Point *P = malloc(length * sizeof *P);

    // while(counter<time)
    for (i=0; i<length; i++) 
        xDotDot = DGL(x, xDot);
        xDot = xDot+xDotDot*step;
        x = x+xDot*step;

        // P, not Point
        P[i].x = x;
        P[i].xDot = xDot;
        P[i].counter = counter;

        counter = counter + step;
        // i++;
    

    return P; // P

然后打电话

PhasePtr = runSimulation(time, x_0, length);

"%g"

提示:使用"%.3g" 打印double 而不是%.3f,因为它可以更好地处理大值和小值。

【讨论】:

变量Point 的问题是使程序真正时髦的原因。我试图自己理解为什么。 gcc 和 clang 都以相同的方式解释它,所以我猜这不是编译器错误。 我已经使用了该程序而没有超出 OP:s 现有公式的范围,但为了安全起见,我使用了你的。与以前相同的问题 - 直到变量被重命名。 @TedLyngmo 是的,多个问题。紫外线 是的,确实如此。我很高兴-ggdb -fsanitize=address,undefined :-)【参考方案3】:

不要将指针变量命名为与 Point 类型相同的名称。

例子:

Point* runSimulation(double time, double x_0, double step) 
    double x = x_0;
    double xDot = 0;
    double xDotDot = 0;
    double counter = 0;
    int i = 0;

    // is this formula really correct?
    Point* pnt = malloc(time / step * sizeof(Point));

    while(counter < time) 
        xDotDot = DGL(x, xDot);
        xDot = xDot + xDotDot * step;
        x = x + xDot * step;

        pnt[i].x = x;
        pnt[i].xDot = xDot;
        pnt[i].counter = counter;

        counter = counter + step;
        i++;
    

    return pnt;

您还应该在完成后在main 中执行free(PhasePtr); 以释放内存。

【讨论】:

以上是关于程序的错误输出,使用指向结构数组的指针的主要内容,如果未能解决你的问题,请参考以下文章

结构中指向数组的 cudaFree 指针上的 CUDA 分段错误

Arduino指向结构变量的指针和指向结构数组的指针打印输出

指向结构数组的指针在输入值时崩溃

添加指向数组的指针时出现分段错误

指向数组部分的指针。过滤数组的操作

将指向 int 数组的指针传递给成员函数,错误:数组下标的无效类型“int [int]”