Forum: Compiler & IDEs Probleme mit Variablen in Funktion


von qwertz (Gast)


Lesenswert?

Hallo,

ich habe eine scheinbar triviale Funktion geschrieben, in welcher in 
einer Schleife eine Variable hochgezählt und eine Funktion aufgerufen 
wird.
Der Funktion wird die Variable übergeben.

Das ganze funktioniert nicht richtig. Die Variable nimmt ständig 
merkwürdige Werte an?!
1
int Funktion_1(struct dev *device)
2
{
3
int ii = 0;
4
int ii_temp = 0;
5
6
printf("check for devices:\n");
7
8
[...]
9
 
10
do
11
        {
12
            printf("device count: %i\n", device->count);
13
            printf("ii: %i\n", ii);
14
            printf("ii_temp: %i\n", ii_temp);
15
16
            status = Funktion_2(device, ii_temp, INIT_COMPLETE);
17
18
            if( status == 1 )
19
            {
20
                printf("ii: %i\n", ii);
21
                printf("ii_temp: %i\n", ii_temp);
22
                printf("init complete Modul ID : %x\n", device->modul[ii_temp].id);
23
            }
24
            else
25
            {
26
                error_flag++;
27
                printf("error flag: %i\n", error_flag);
28
            }
29
30
            ii++;
31
            ii_temp = ii;
32
            printf("i: %i\n", ii);
33
            printf("i_temp: %i\n", ii_temp);
34
35
        }while(ii < device->count);

Als Ausgabe kommt z.B.:
1
check for devices:
2
device count 1
3
ii: 0
4
ii_temp: 0
5
ii: 0
6
ii_temp: 0
7
init_complete Modul ID: 4
8
ii: -1238642063
9
ii_temp: -1238642063
10
device count 1
11
ii: -1238642063
12
ii_temp: -1238642063
...ab hier hängt sich das Programm auf.
Das Verhalten ist aber nicht immer reproduzierbar.
Was läuft falsch? Wo kommt plötzlich der Inhalt her?

von Oliver (Gast)


Lesenswert?

Aus Zeile 42 von Funktion_2 ?

Irgendwo schreibst du dir da den Stack kaputt. Das passiert aber nicht 
in den gezeigten Zeilen, ausser, der Stack ist viel zu klein, und läuft 
einfach so über.

Oliver

von qwertz (Gast)


Lesenswert?

> Irgendwo schreibst du dir da den Stack kaputt.

Sowas dachte ich mir auch. Aber ich weiß nicht wo das geschehen soll.
Die Funktion_2 kann das doch nicht ohne weitere machen, oder?

> der Stack ist viel zu klein
Legt man dessen Größe irgendwo fest?

Das Problem tritt nicht immer auf. Manchmal funktioniert es, manchmal 
aber nicht...

von qwertz (Gast)


Lesenswert?

Was auch ganz oft passiert:

Als Ausgabe kommt z.B.:

check for devices:
device count 2
ii: 1
ii_temp: 1
ii: 1
ii_temp: 1
init_complete Modul ID: 4
ii: 1
ii_temp: 1
device count 1
ii: 1
ii_temp: 1

d.h. die Variablen werden wieder auf 0 gesetzt?!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Kompletten Code zeigen und Target-Prozessor/OS nennen. Sonst wird das 
nix.

von Dennis S. (eltio)


Lesenswert?

Und bitte die "[c]"-Tags nutzen..

von qwertz (Gast)


Lesenswert?

Würde es reichen die beiden Funktionen komplett zu zeigen?

Linux raspberrypi 3.6.11+

von qwertz (Gast)


Lesenswert?

1
int connect_and_send_msg(struct dev *device, int modul, int message)
2
{
3
    struct can_frame in_frame_;
4
    int status       = 0;
5
    int conn_attemps = 0;
6
7
    do
8
    {
9
        can_send(message, device->modul[modul].id);
10
11
        usleep(10000);
12
        status = can_dump(&in_frame_);
13
14
        if ( (status == 1) && (in_frame_.can_id == device->modul[modul].id) && (in_frame_.can_dlc == 1) && (in_frame_.data[0]==OK) )
15
        {
16
            return 1;
17
        }
18
        else
19
        {
20
            conn_attemps++;
21
            usleep(5000);
22
        }
23
24
    }while( conn_attemps <= 5 );
25
26
    if( conn_attemps >= 5 )
27
    {
28
        printf("ERROR: no connection to module with ID %i\n", device->modul[modul].id);
29
        return 0;
30
    }
31
32
}
33
34
/* get CAN devices */
35
int get_can_module_2(struct dev *device)
36
{
37
    printf("check for CAN devices:\n");
38
39
    struct can_frame in_frame;
40
    int status      = 0;
41
    int modul_count = 0;
42
    int requests    = 0;
43
    int error_flag  = 0;
44
45
    int ii_temp      = 0;
46
    int ii           = 0;
47
48
    // Abfrage aller Module
49
    do
50
    {
51
        can_send(GET_VERSION,ID_PI);
52
        usleep(5000);
53
        status = can_dump(&in_frame);
54
55
        if ( (status == 1) && (in_frame.can_dlc == 0) )
56
        {
57
            device->modul[modul_count].id = in_frame.can_id;
58
            connect_and_send_msg(device, modul_count, INIT);
59
60
            modul_count++;
61
            device->count = modul_count;
62
            requests = 0;
63
        }
64
        else
65
        {
66
            requests++;
67
            //printf("requests: %i\n",requests);
68
            usleep(5000);
69
        }
70
71
    }while( requests <= 5 );
72
73
    // keine Module angeschlossen??
74
    if ( device->count == 0 )
75
    {
76
        printf("no module\n");
77
        return 0;
78
    }
79
80
    // Freigabe aller Module
81
    if ( device->count > 0 )
82
    {
83
        do
84
        {
85
            printf("device count: %i\n", device->count);
86
            printf("ii: %i\n", ii);
87
            printf("ii_temp: %i\n", ii_temp);
88
89
            status = connect_and_send_msg(device, ii_temp, INIT_COMPLETE);
90
91
            if( status == 1 )
92
            {
93
                printf("ii: %i\n", ii);
94
                printf("ii_temp: %i\n", ii_temp);
95
                printf("init complete CAN-Modul ID : %x\n", device->modul[ii_temp].id);
96
            }
97
            else
98
            {
99
                error_flag++;
100
                printf("error flag: %i\n", error_flag);
101
            }
102
103
            ii++;
104
            ii_temp = ii;
105
            printf("i: %i\n", ii);
106
            printf("i_temp: %i\n", ii_temp);
107
108
        }while(ii < device->count);
109
110
        if( error_flag != 0 )
111
        {
112
            return 0;
113
        }
114
    }
115
    
116
    return 1;
117
118
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

qwertz schrieb:
> Würde es reichen die beiden Funktionen komplett zu zeigen?

Vielleicht. Kann aber auch sein, dass irgendwo vorher schon Daten im 
Speicher (z.B. durch Overflows) überschrieben wurden.

Aber dann bitte auch alle (globalen) Variablen und Typ-definitionen, die 
Du in den beiden Funktionen verwendest, zeigen, insb. structs etc.

> Linux raspberrypi 3.6.11+

Ah, ok.

von qwertz (Gast)


Lesenswert?

> Ah, ok.

Sarkasmus?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Wie stellst Du eigentlich sicher, dass modul_count im ersten 
do-while-Block (in der Funktion get_can_module_2()) nicht gegen 
unendlich läuft?

Bitte noch alle globalen Variablen-Definitionen bzw. Typ-Deklarationen 
wie structs zeigen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

qwertz schrieb:
>> Ah, ok.
>
> Sarkasmus?

Hättest Du mal auf meine Benutzerseite geklickt, hättest Du auf einen 
Schlag erkennen können, dass ich ein alter Linux-Hase bin ;-)

von qwertz (Gast)


Lesenswert?

struct dev:
1
// Gateway ID Parameter
2
struct id_ {
3
    int kfz_id;
4
    int kfz_id_counter;
5
    int rep_id;
6
};
7
8
// Gateway Parameter
9
struct gateway_ {
10
    int listen_only_flag;
11
    int bitrate;
12
    int filter_0;
13
    int filter_1;
14
    int filter_2;
15
    int filter_3;
16
    int filter_4;
17
    int filter_5;
18
    int mask_0;
19
    int mask_1;
20
    int kfz_id_count;
21
    struct id_ id[GATEWAY_KFZ_ID_MAX];
22
};
23
24
// Modul Paramter
25
struct modul_ {
26
    int id;
27
    int typ;
28
    int option;
29
    int comm_flag = 0;
30
    //struct gateway_ gateway[GATEWAY_MAX];
31
    struct gateway_ gateway;
32
};
33
34
// Geräte Parameter
35
struct dev {
36
    int count;
37
    int terminal_modchange = 1;
38
    int terminal_modshow = 1;
39
    struct modul_ modul[DEVICE_MAX];
40
};

Die struct can_frame ist im header
#include <linux/can.h> bzw.
#include <linux/can/raw.h>

von qwertz (Gast)


Lesenswert?

> Wie stellst Du eigentlich sicher, dass modul_count im ersten
> do-while-Block (in der Funktion get_can_module_2()) nicht gegen
> unendlich läuft?

Bisher noch nicht.

von Oliver (Gast)


Lesenswert?

qwertz schrieb:
> Würde es reichen die beiden Funktionen komplett zu zeigen?

Natürlich nicht.


qwertz schrieb:
> int get_can_module_2(struct dev *device)
> {
>     printf("check for CAN devices:\n");
>
>     struct can_frame in_frame;
>     int status      = 0;
>     int modul_count = 0;
...
>         status = can_dump(&in_frame);

Rate mal, welche Funktion wir als nächstes sehen wollen.

Oliver

von Εrnst B. (ernst)


Lesenswert?

Evtl. als Zwischenscritt sinnvoll:

Aktivier beim compilieren deines Programmes alle 
Compiler-Warning-Optionen.
Reparier deinen Quelltext, bis der Compiler nichts mehr zu meckern 
findet.

Dann: Compilier mit Stack-Protector
(-fstack-protector, -fstack-protector-strong, ...)
Schau nach, ob das Problem noch auftritt, oder ob du einen 
Reproduzierbaren Programmabbruch bekommst.

von qwertz (Gast)


Lesenswert?

1
int can_dump(struct can_frame *frame)
2
{
3
    int nbytes  = 0;
4
    int stat    = 0;
5
6
    stat = can_poll(100); // socket, timeout [ms]
7
8
    /* clear CAN-Data-Struct */
9
    frame->data[8] = { 0 };
10
11
    if(stat==1)
12
    {
13
        nbytes = read(skt, frame, sizeof(*frame));
14
15
        if (nbytes < 0)
16
        {
17
            printf("can raw socket read ERROR\n");
18
            return -1;
19
        }
20
21
        // paranoid check ...
22
        if (nbytes < sizeof(struct can_frame))
23
        {
24
            printf("read: incomplete CAN frame\n");
25
            return -2;
26
        }
27
28
        return 1;
29
    }
30
31
    else if(stat==0)
32
    {
33
        //printf ("CAN message timeout\n");
34
        for(int i=0;i<8;i++)
35
        {
36
            frame->data[i] = 0;
37
38
        }
39
        frame->can_id = 0;
40
        return 0;
41
    }
42
43
    else if(stat==-1)
44
    {
45
        printf ("invalid socketdescriptor\n");
46
        return -3;
47
    }

von qwertz (Gast)


Lesenswert?

1
int can_poll(int time)
2
{
3
    struct pollfd pfd[1];
4
    int32_t ret;
5
6
    pfd[0].fd = skt;
7
    pfd[0].events = POLLIN;
8
9
    ret = poll (pfd, 1, time);
10
11
    if (ret > 0)
12
    {
13
        if (pfd[0].revents & POLLERR)
14
        {
15
           return -1;
16
        }
17
18
        if (pfd[0].revents & POLLIN)
19
        {
20
            return 1;
21
        }
22
23
    }
24
    else
25
    {
26
       return 0;
27
    }
28
29
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

qwertz schrieb:
>> Wie stellst Du eigentlich sicher, dass modul_count im ersten
>> do-while-Block (in der Funktion get_can_module_2()) nicht gegen
>> unendlich läuft?
>
> Bisher noch nicht.

Dann sichere das ab. Wenn modul_count >= DEVICE_MAX wird, dann 
überschreibst Du Dir den Speicher.

von Karl H. (kbuchegg)


Lesenswert?

qwertz schrieb:

>     /* clear CAN-Data-Struct */
>     frame->data[8] = { 0 };
>

Nope.
Das macht nicht das was du denkst das es macht.

von qwertz (Gast)


Lesenswert?

>>     /* clear CAN-Data-Struct */
>>     frame->data[8] = { 0 };
>>
>
> Nope.
> Das macht nicht das was du denkst das es macht.

Hab es geändert.
1
 /* clear CAN-Data-Struct */
2
    for(int b=0; b<8; b++)
3
    {
4
        frame->data[b] = 0;
5
    }

Außerdem habe ich alle Warnungen ausgemerzt und jetzt läuft es.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

qwertz schrieb:
> Außerdem habe ich alle Warnungen ausgemerzt und jetzt läuft es.

Woran lag es? Schade, dass Du die Warnungen hier nicht vorher gepostet 
hast.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.