Forum: PC-Programmierung Speicher nicht richtig verwaltet


von verwirrter Frickler (Gast)


Lesenswert?

Nach dem Compilieren und dem Aufruf via Kommandozeile macht mein 
Programm auf einem Raspberry Pi scheinbar brav was es soll:
sudo /home/pi/libmodbus/Raspi_III_GPIO_RS-485/readSDM120 -s /dev/ttyS0 
-r30007
gibt einen Meßwert (hier: Ampere) an stdout aus:
0.1
Ich habe die zu übergebenden Parameter in vielen Kombinationen getestet 
und es gab keine Anomalien.


Wenn ich aber die gleiche Zeile via exec-Node von node-red aufrufe, 
kommt im Debug-Fenster das dabei raus:
"ERROR (ignored): Non-option argument 1504101045512↵0.1↵"
Die Fehlermeldung "ERROR (ignored): Non-option argument" habe ich zum 
Debuggen eingbaut, sie kann nur kommen wenn ein zweiteiliger Parameter 
(zB. -s /devTTYS0) nicht vollständig wäre; das ist aber hier nicht der 
Fall.

Die Konsole unter node-red gibt:
pi : TTY=unknown ; PWD=/home/pi ; USER=root ; 
COMMAND=/home/pi/libmodbus/Raspi_III_GPIO_RS-485/readSDM120 -s 
/dev/ttyS0 -r30007 1504101045512

Wo kommt diese 13-stellige Zahl her? Könnten das die Reste eines 
kaputten Zeigers o.ä. sein...?


Der Messwert kommt zwar (ganz am Schluß), aber vorher kommt Datenmüll. 
Als ob Speicher nicht freigegeben/geflusht o.ä vergessen worden wäre.

Gleich am Anfang von main werden die Kommandozeilenparameter 
ausgewertet.

Vorweg: Ich mache das Auswerten der Kommandozeilenargumente das erste 
mal, und bin darin noch ziemlich unsicher...
1
struct someStuff_t {
2
    int SDM120reg;
3
    int debug;
4
    char serial[20];
5
    };
6
7
int main(int argc, char *argv[])
8
{
9
  ...
10
  ...
11
  ...
12
13
    struct someStuff_t someStuff;
14
15
// Step1: Extract the selected register and serial interface
16
// Example:
17
// readSDM120 -d 1 -s /dev/ttyS0 -r 30013
18
// DEBUG Mode 1, svalue = /dev/ttyS0, rvalue => SDM120_POWER
19
20
    if (argc == 1) {
21
        printf ("Use with command line options (-h for help).\n");
22
        return (0);
23
  }
24
25
    evaluate_main (argc, argv, &someStuff);  // someStuff wird mit den ausgewerteten Kommandozeilen-Argumenten gefüllt
26
  ...
27
  ...
28
  ...
29
}
30
31
32
33
34
35
int evaluate_main (int eval_argc, char **eval_argv, struct someStuff_t *stuff)
36
{
37
38
  int dflag = 0;  //debug
39
  int sflag = 0;  //serial interface
40
  int rflag = 0;  //register flag
41
  char *svalue = NULL;  //serial interface as string
42
  char *rvalue = NULL;  //register value as string
43
  char *dvalue = NULL;  //debug mode as string : 1 or 2
44
  int base = 10;
45
  char *endptr;
46
  int index;
47
  int c;
48
  opterr = 0;
49
50
/* Get data from SDM120 Modbus device
51
 Parameter:
52
 -d debug mode
53
 -s serial
54
 -r Input register (3x range) start address of the slave device. Always 'address' and 'address+1' are fetched
55
    as IEEE-754 float is stored in 2x16 bit registers
56
57
 example: fetch current from SDM120 via /dev/ttyS0
58
 SDM120 -d -s /dev/ttyS0 -r 30007
59
*/
60
61
  while ((c = getopt (eval_argc, eval_argv, "d:hs:r:")) != -1)
62
    switch (c)
63
      {
64
      case 'h':
65
        //Help
66
        printf("SDM120 readout.\n");
67
        printf("Use with option:\n");
68
        printf(" -h  This help here\n");
69
        printf(" -d  Debug mode, 1: read single input register, 2: read all input registers\n");
70
        printf(" -s  Serial interface: /dev/ttyS0, /dev/ttyACM0...\n");
71
        printf(" -r  Register to be read: 30001, 30006, 30343...\n");
72
        printf("Example: SDM120 -d 1 -s /dev/ttyS0 -r 30001\n\n");
73
        printf("\n");
74
        exit ();
75
76
       case 'd':
77
        printf ("DEBUG mode\n");
78
        dvalue = optarg;
79
        stuff->debug = strtol(dvalue, &endptr, base);
80
        if (stuff->debug == 1) dflag = 1;
81
        break;
82
83
       case 's':
84
        sflag = 1;
85
      //  svalue = optarg;
86
        strcpy (stuff->serial, optarg);
87
        break;
88
89
      case 'r':
90
    //    rvalue = optarg;
91
        // val =
92
        //stuff->SDM120reg = strtol(rvalue, &endptr, base);
93
        stuff->SDM120reg = strtol(optarg, &endptr, base);
94
        rflag = 1;
95
        break;
96
97
      case '?':
98
        if ((optopt == 'r') || (optopt == 's')||(optopt == 'd'))
99
          fprintf (stderr, "Option -%c requires an argument.\n", optopt);
100
        else if (isprint (optopt))
101
          fprintf (stderr, "Unknown option `-%c'.\n", optopt);
102
        else
103
          fprintf (stderr,
104
                   "Unknown option character `\\x%x'.\n",
105
                   optopt);
106
        return 1;
107
      default:
108
        abort ();
109
      }
110
111
     if (stuff->debug == 1) printf ("Local: dflag = %d, sflag = %d rflag = %d, svalue = %s, rvalue = %s\n",
112
                dflag, sflag, rflag, svalue, rvalue);
113
114
  for (index = optind; index < eval_argc; index++)
115
    printf ("ERROR (ignored): Non-option argument %s\n", eval_argv[index]);
116
117
  return 0;
118
119
}

Irgendetwas geht in dieser Auswerteroutine böse daneben - hat jemand 
eine Idee?

von guest (Gast)


Lesenswert?

Das wichtigste hast Du vergessen

verwirrter Frickler schrieb:
> Wenn ich aber die gleiche Zeile via exec-Node von node-red aufrufe

Ja wie denn? Deine node-red Konsole zeigt Dir doch, das die Zahl bereits 
als Parameter an Dein Programm übergeben wird, Deine Routine arbeitet 
also völlig korrekt und die Fehlermeldung passt auch.

von verwirrter Frickler (Gast)


Lesenswert?

Nachdem ich im ersten Moment über deine Aussage gerätselt habe, habe ich 
doch nochmal nachgedacht - und tatsächlich: Defaultmäßig ist bei den 
Eigenschaften des Nodes "+ Append  msg.payload" angehakt. Ich habe das 
nicht gesehen.
Nun ist der Müll weg. Mein selbstgeschriebener Code funktioniert 
ausnahmsweise mal wie er soll. HA!

Vielen Dank für den Tip. Manchmal brauchts einen Anstoß...

von guest (Gast)


Lesenswert?

Damit Du beim nächsten Mal vielleicht weniger rätseln mußt :)

"COMMAND=/home/pi/libmodbus/Raspi_III_GPIO_RS-485/readSDM120 -s
/dev/ttyS0 -r30007 1504101045512"

Das war die entscheidende Zeile in Deinem Post. Da sieht man den Aufruf 
Deines Programs samt der komischen Zahl als letzem Parameter.

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.