valgrind mag regcomp mit REG_ICASE nicht?

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

valgrind mag regcomp mit REG_ICASE nicht?

Beitrag von RobertDebiannutzer » 17.10.2018 14:49:49

regcomp mit "REG_EXTENDED | REG_NOSUB | REG_ICASE | REG_NEWLINE"
dann

Code: Alles auswählen

(dev)user@hostname:~/dev/rovi$ make clean && make && cp rovi ~/test/ && cp -ar . ~/backup/rovi
cleaning
rovi build options:
CFLAGS   = -ggdb -std=c99 -pedantic -Wall -Wextra -Werror -O0 -I. -I/usr/include -DVERSION="0.3" -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L
LDFLAGS  = -L/usr/lib -lc -lncursesw
CC       = cc
CC rovi.c
CC -o rovi
dann

Code: Alles auswählen

(dev)user@hostname:~/dev$ valgrind --leak-check=full --track-origins=yes -v ~/test/rovi ~/testfile
[...]
==26031== ERROR SUMMARY: 3 errors from 1 contexts (suppressed: 0 from 0)
==26031== 
==26031== 3 errors in context 1 of 1:
==26031== Conditional jump or move depends on uninitialised value(s)
==26031==    at 0x4EFEFD9: re_compile_fastmap_iter.isra.24 (regcomp.c:328)
==26031==    by 0x4F07634: re_compile_fastmap (regcomp.c:276)
==26031==    by 0x4F07D0A: regcomp (regcomp.c:509)
==26031==    by 0x10CAD5: setup (rovi.c:382)
==26031==    by 0x10D08F: main (rovi.c:522)
==26031==  Uninitialised value was created by a stack allocation
==26031==    at 0x4F04540: parse_expression (regcomp.c:2224)
==26031== 
==26031== ERROR SUMMARY: 3 errors from 1 contexts (suppressed: 0 from 0)
regcomp mit "REG_EXTENDED | REG_NOSUB | REG_NEWLINE"
dann

Code: Alles auswählen

(dev)user@hostname:~/dev/rovi$ make clean && make && cp rovi ~/test/ && cp -ar . ~/backup/rovi
cleaning
rovi build options:
CFLAGS   = -ggdb -std=c99 -pedantic -Wall -Wextra -Werror -O0 -I. -I/usr/include -DVERSION="0.3" -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L
LDFLAGS  = -L/usr/lib -lc -lncursesw
CC       = cc
CC rovi.c
CC -o rovi
dann

Code: Alles auswählen

(dev)user@hostname:~/dev$ valgrind --leak-check=full --track-origins=yes -v ~/test/rovi ~/testfile
[...]
==26163== LEAK SUMMARY:
==26163==    definitely lost: 0 bytes in 0 blocks
==26163==    indirectly lost: 0 bytes in 0 blocks
==26163==      possibly lost: 0 bytes in 0 blocks
==26163==    still reachable: 1,765,521 bytes in 358 blocks
==26163==         suppressed: 0 bytes in 0 blocks
==26163== Reachable blocks (those to which a pointer was found) are not shown.
==26163== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==26163== 
==26163== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==26163== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Würde mich freuen, wenn mir jemand was dazu sagen könnte!

Benutzeravatar
king-crash
Beiträge: 722
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

Re: valgrind mag regcomp mit REG_ICASE nicht?

Beitrag von king-crash » 18.10.2018 10:05:10

Was willst du denn hören?
Dass niemand wirklich dein Problem kennt?
Dass deine Überschrift komplett unpassend ist?
Dass dein Programm beim ersten Versuch scheinbar einen von einer nicht initialisierten Variable bedingten Sprung durchführen will?

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: valgrind mag regcomp mit REG_ICASE nicht?

Beitrag von RobertDebiannutzer » 18.10.2018 10:34:01

Offenbar habe ich die Situation unzureichend beschrieben... 8O

Um dieses Stückchen geht es:

Code: Alles auswählen

	for (i=0; i<len; i++) {
		if (regcomp(&repat[i], cos[i].re,
					REG_EXTENDED | REG_NOSUB | REG_ICASE | REG_NEWLINE) != 0) {
			errfunc(__FILE__, __LINE__, 1);
		}
	}
Am Rest des Programmes wurde zwischen den beiden Kompilierungen nichts verändert! Nur wurde eben einmal REG_ICASE gestrichen.
man 3 regcomp: https://manpages.debian.org/stretch/man ... .3.en.html

Wie soll ich bitte vorher wissen, ob jemand mein Problem kennt und/oder was dazu sagen kann? Weil ich das nicht weiß, frage ich ja! Ich bin halt Anfänger und habe kürzlich erst valgrind als Testwerkzeug entdeckt. Das hat mir auch schon geholfen, nur hier frage ich mich eben, was das hier genau bedeutet. Letztendlich ist es vielleicht ein Bug in regcomp, sonst würde valgrind ja nicht sagen:

Code: Alles auswählen

==26031==  Uninitialised value was created by a stack allocation
==26031==    at 0x4F04540: parse_expression (regcomp.c:2224)
?
Jetzt könnte ich natürlich in die libc-Sourcen schauen, also in regcomp.c, Zeile 2224, doch ich fürchte, das ich damit nicht zurechtkommen werde.

Benutzeravatar
king-crash
Beiträge: 722
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

Re: valgrind mag regcomp mit REG_ICASE nicht?

Beitrag von king-crash » 18.10.2018 11:10:45

Habe ich das richtig verstanden, dass das ein Fremdprogramm ist, indem du etwas geändert hast?
Zu welchem Zweck?
Warum hast du valgrind verwendet?
Die Zeile, die Valgrind anzeigt muss nicht bedeuten, dass hier der eigentliche Fehler liegt. Und das liegt nicht an valgrind sondern in der Natur der Sache.

Ein Beispiel:

Code: Alles auswählen

#include <ctype.h>

void funktion(char *str)
	{
	str[0] = tolower(str[0]);
	}

int main(void)
	{
	char test[2];
	funktion(test);
	return 0;
	}
==31261== Conditional jump or move depends on uninitialised value(s)
==31261== at 0x4E640FF: tolower (ctype.c:46)
==31261== by 0x1086CC: funktion (test.c:5)
==31261== by 0x1086EB: main (test.c:11)
Der Fehler liegt aber nicht in der libc.
Passiert überhaupt ein Fehler?

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: valgrind mag regcomp mit REG_ICASE nicht?

Beitrag von RobertDebiannutzer » 18.10.2018 11:38:42

king-crash hat geschrieben: ↑ zum Beitrag ↑
18.10.2018 11:10:45
Habe ich das richtig verstanden, dass das ein Fremdprogramm ist, indem du etwas geändert hast?
Hmja, erst war es ein Fremdprogramm, bei dem ich was geändert habe. Dann habe ich aber immer mehr geändert und nun schreibe ich es neu.
king-crash hat geschrieben: ↑ zum Beitrag ↑
18.10.2018 11:10:45
Zu welchem Zweck?
Ist das wichtig?
king-crash hat geschrieben: ↑ zum Beitrag ↑
18.10.2018 11:10:45
Warum hast du valgrind verwendet?
Um zu überprüfen, ob ich alles richtig gemacht habe natürlich... Weil ich nun das erste Mal selber dynamische Speicherverwaltung einsetze.
king-crash hat geschrieben: ↑ zum Beitrag ↑
18.10.2018 11:10:45
Passiert überhaupt ein Fehler?
Nein, die Funktion ist nicht beeinträchtigt.

Aber:
Most hackers actually don’t care much about code quality. Thus, if they get something working which seems to solve a problem, they stick with it. If this kind of software development is applied to the same source code throughout its entire life-cycle, we’re left with large amounts of code, a totally screwed code structure, and a flawed system design. This is because of a lack of conceptual clarity and integrity in the development process.
Quelle: http://suckless.org/philosophy/

Dein Beispiel kann ich nachvollziehen, aber außer dem "REG_ICASE" habe ich ja nichts geändert. Somit kann es doch nicht am Rest des Programms liegen, wenn valgrind mit "REG_ICASE" was meldet und ohne nicht? Oder hat regcomp mit bestimmten REs und REG_ICASE ein Problem? Dazu habe ich schon gesucht, aber leider (noch?) nichts gefunden.

eggy
Beiträge: 3331
Registriert: 10.05.2008 11:23:50

Re: valgrind mag regcomp mit REG_ICASE nicht?

Beitrag von eggy » 18.10.2018 13:32:25

Nur geraten, nicht in den Code geschaut, kann was völlig anderes sein:
Ich geh davon aus, dass es daran liegt, dass der Funktionsaufruf durch die Parameter intern andere Subfunktionen aufruft, und da halt mal irgendwas uninitialisiert verwendet wird. Jetzt könnte man hingehen und schauen, wo das in den Bibliotheken der Fall ist, und gegebenenfalls nen Patch einreichen - oder man ignoriert das einfach erstmal (bzw sagt Vallgrind, dass es bestimmte Sachen ignorieren soll, wie steht in der Doku/Internet).

Für obrige Theorie spricht der Absatz in der Manpage "REG_ICASE Do not differentiate case. Subsequent regexec() searches using this pattern buffer will be case insensitive" und die Fehlermeldung in Bezug auf tolower(), und dass der Fehler nur auftritt, wenn tolower gerufen wird, was hier wohl nur bei ICASE der Fall ist - ob die Annahme stimmt, kannst Du ja mal selbst versuchen zu verfolgen.

Benutzeravatar
king-crash
Beiträge: 722
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

Re: valgrind mag regcomp mit REG_ICASE nicht?

Beitrag von king-crash » 19.10.2018 11:06:56

Ist das wichtig?
Durchaus. Die unter Anderem möglichen Antworten "ich mache das um Programmieren zu lernen und habe einfach Spaß daran" oder "ein Bug soll schnell gefixt werden" geben schon verschiedene Lösungswege vor.
Nein, die Funktion ist nicht beeinträchtigt.
Was uns zu "ich will was lernen" (und bin unfähig das frühzeitig zu kommunizieren) bringt.

Wie so eine Meldung zustande kommt habe ich bereits geschildert, valgrind gibt dir weitere Hinweise:
==26031== Uninitialised value was created by a stack allocation
==26031== at 0x4F04540: parse_expression (regcomp.c:2224)

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: valgrind mag regcomp mit REG_ICASE nicht?

Beitrag von RobertDebiannutzer » 19.10.2018 14:24:29

Also mit den Fehlermeldungen finde ich folgendes:

In parse_expression() wird in Z. 2225 (in 2224 ist eine Klammer) der Pointer *dfa belegt:

Code: Alles auswählen

  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
Das muss wohl der gleiche sein, der in re_compile_fastmap_iter() in Z. 328 als Bedingung in einem while-loop genutzt wird:

Code: Alles auswählen

	      while (++node < dfa->nodes_len
		     &&	dfa->nodes[node].type == CHARACTER
		     && dfa->nodes[node].mb_partial)
(Quelle der beiden und der folgenden Codeschnipsel: Datei regcomp.c, von https://packages.debian.org/stretch/libc6 heruntergeladen).

Wenn nun dfa "uninitialisiert" ist, muss wohl "preg->buffer" NULL sein?
Der Fehler (wenn tatsächlich einer vorliegt) findet nur statt, wenn REG_ICASE aktiviert ist, denn nur dann ist auch RE_ICASE aktiviert und nur dann bewahrheitet sich das "if" in re_compile_fastmap_iter, Z. 318 und nur dann kommt man logischerweise zu dem while-loop in Z. 328.

Möglicherweise liegt der Fehler in Z. 779:

Code: Alles auswählen

      preg->buffer = NULL;
in

Code: Alles auswählen

  err = re_string_construct (&regexp, pattern, length, preg->translate,
			     syntax & RE_ICASE, dfa);
  if (BE (err != REG_NOERROR, 0))
    {
    re_compile_internal_free_return:
      free_workarea_compile (preg);
      re_string_destruct (&regexp);
      free_dfa_content (dfa);
      preg->buffer = NULL;
      preg->allocated = 0;
      return err;
    }
?
Oder es liegt in der Funktion re_string_construct aus dem obigen Codeschnipsel, welche sich in der Datei regex_internal.c in glibc befindet und laut Kommentar for Allocation von Buffern zuständig ist.
Ich weiß noch nicht, ob ich das weiter verfolgen soll, oder lieber versuchen soll einen Bug-Report zu erstellen...

Benutzeravatar
king-crash
Beiträge: 722
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

Re: valgrind mag regcomp mit REG_ICASE nicht?

Beitrag von king-crash » 23.10.2018 08:26:42

Wenn "preg->buffer" NULL ist, sollte dfa eigentlich initialisiert sein.
Gibt es ein Minimalbeispiel, mit dem ich das bei mir nachvollziehen kann?

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: valgrind mag regcomp mit REG_ICASE nicht?

Beitrag von RobertDebiannutzer » 30.10.2018 18:28:27

Ich habe versucht, meinen "Bug" mit einem Minimalbeispiel nachzustellen, das hat aber nicht funktioniert. Ich werde also nochmal schauen müssen, wie es nun genau bei meinem Programm zu diesem Fehler kommen konnte.
Vielen Dank erstmal bis hierher, bei neuen Erkenntnissen/Fragen werde ich mich wieder melden (kann allerdings dauern, da ich gerade echt viel zu tun habe...).

Antworten