ubuntuusers.de

Merkwürdiger `malloc()`-Crash mit Python-Programm

Status: Gelöst | Ubuntu-Version: Ubuntu 24.04 (Noble Numbat)
Antworten |

UlfZibis

Anmeldungsdatum:
13. Juli 2011

Beiträge: 3440

Wohnort: Köln

Hallo,

es geht um folgende Programm:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#!/usr/bin/env python3
import csv
import re
import subprocess
import sys
from pathlib import Path
from pprint import pprint
from pymediainfo import MediaInfo


def file(file_path):
    result = subprocess.check_output(
        ["file", "--brief", str(file_path)], text=True)
    return [part.strip() for part in result.split(",")]


def detect_volumes(file_path):
    result = subprocess.run(
        ["ffmpeg", "-hide_banner", "-nostdin",
            *("-i", str(file_path)),
            *("-af", "volumedetect"), *("-f", "null"), "/dev/null"],
        capture_output=True,
        check=True
    )
    return (
        float(re.search(rb"mean_volume: (\S*)", result.stderr)[1]),
        float(re.search(rb"max_volume: (\S*)", result.stderr)[1])
    )
#    volumes = { # use dictionary (= HashMap)
#        match[1]: float(match[2])
#        for match in re.finditer(rb"m(ean|ax)_volume: (\S*)", result.stderr)
#    }
#    return (volumes[b"ean"], volumes[b"ax"])


def main():
    if len(sys.argv) <= 3:
        print("Usage: ./volume-analysis.py START_PATH .mp3|.flac THRESHOLD [--verbose]")
        sys.exit(1)
    start_path = Path(sys.argv[1])
    extension = sys.argv[2]
    threshold = float(sys.argv[3])
    verbose = "--verbose" in sys.argv[4:]
    album_count = 0
    album_mean_sum = 0.0
    album_mean_min = 0.0
    album_mean_max = -128.0
    album_peak_sum = 0.0
    album_peak_min = 0.0
    album_peak_max = -128.0
    albums_with_low_volume = []
    albums_with_mixed_mode = []
    albums_with_mixed_constant_rate = []
    files_without_bitrate = []
    files_with_comment = []
    files_with_notes = []
    files_with_audio_comment = []
    files_with_errors = []

    with (
        open(f"mediainfo_albums{extension}.csv", "w", encoding="utf-8", newline=""
        ) as csv_file,
        open(f"mediainfo_files{extension}.csv", "w", encoding="utf-8", newline=""
        ) as verbose_csv_file
    ) :
        csv_writer = csv.writer(csv_file, delimiter=';')
        verbose_csv_writer = csv.writer(verbose_csv_file, delimiter=';')
        csv_writer.writerow(["No","Path","Size","Mode","Bit rate"])
        verbose_csv_writer.writerow(["Album","No","Path","Size","Settings","Channels",
        "Sampling rate","Bit depth","Mode","Bit rate","Vol mean","Vol max"])

        directory_paths = [start_path] + sorted(
            path for path in start_path.rglob("*") if path.is_dir()
        )
        for directory_path in directory_paths :
            file_count = 0
            mean_sum = 0.0
            mean_min = 0.0
            mean_max = -128.0
            peak_sum = 0.0
            peak_min = 0.0
            peak_max = -128.0
            rate_mode = "None"
            rate_sum = 0.0
            rate = 0.0
            rate_old = 0.0
            rate_mixed = False
#            if not (file_paths := sorted(
#                directory_path.glob("*"+extension, case_sensitive=False)
#                # directory_path.glob("*.[fF][lL][aA][cC]") # before Python 3.12
#            )) : continue
            if not (file_paths := sorted(path for path in
                directory_path.glob("*"+extension, case_sensitive=False)
                # directory_path.glob("*.[fF][lL][aA][cC]") # before Python 3.12
                    if (extension == ".flac" or not path.with_suffix(".flac").exists())
            )) : continue

            album_count += 1
            for file_path in file_paths :
                if verbose :
                    print(file_path)
                try:
                    media_info = MediaInfo.parse(file_path)
                    general = media_info.general_tracks[0]
                    audio = media_info.audio_tracks[0]
                    # print(f" general comment: {general.comment}, audio comment: {audio.comment}, abcd: {audio.abcd},")
                    # print(f" audio size: {audio.stream_size} bytes, file size: {general.file_size} bytes.")
                    # pprint(general.to_data())
                    # pprint(audio.to_data())
                    if verbose :
                        print(f"  Format={audio.format}, Format settings={audio.format_settings},",
                            f"Format profile={audio.format_profile}, Channel(s)={audio.channel_s},",
                            f"Bit rate mode={audio.bit_rate_mode}, Bit rate={audio.bit_rate},",
                            f"Sampling rate={audio.sampling_rate}, Bit depth={audio.bit_depth}")
                    FLAC = "FLAC" in audio.format
                    MP3 = ("MPEG Audio" in audio.format and "Layer 3" in audio.format_profile) or extension == ".mp3"
                    if FLAC or MP3 :
                        mean_volume, max_volume = detect_volumes(file_path)
                        mean_sum += mean_volume
                        mean_min = min(mean_min, mean_volume)
                        mean_max = max(mean_max, mean_volume)
                        peak_sum += max_volume
                        peak_min = min(peak_min, max_volume)
                        peak_max = max(peak_max, max_volume)
                        rate_mode = audio.bit_rate_mode if file_count == 0 else\
                            rate_mode if audio.bit_rate_mode == rate_mode else "Mixed"
                        if entry := audio.bit_rate :
                            rate = float(entry)
                            rate_mixed = rate_mixed or (file_count > 0 and rate != rate_old)
                            rate_sum += (rate_old := rate)
                        else :
                            files_without_bitrate.append(file_path)
                        if general.comment :
                            files_with_comment.append(file_path)
                            print(f"  with general comment: {general.comment}")
                        if general.notes :
                            files_with_notes.append(file_path)
                            print(f"  with general notes: {general.notes}")
                        if audio.comment :
                            files_with_audio_comment.append(file_path)
                            print(f"  with audio comment: {audio.comment}")
                        file_count += 1
                        if verbose :
                            tail = "      ("+str(audio.bit_rate)+", "+str(audio.bit_rate_mode)+")"
                            print("  mean volume: %5.1f dB, peak volume: %5.1f dB%s"
                                %(mean_volume, max_volume, tail))
#                            print(f"  mean volume: {mean_volume: 5.1f} dB,"
#                                f" max volume: {max_volume: 5.1f} dB")

                        # Write values to csv file:
                        values = [album_count, file_count, file_path.name, audio.stream_size,
                            audio.format_settings, audio.channel_s, audio.sampling_rate, audio.bit_depth,
                            audio.bit_rate_mode, audio.bit_rate, mean_volume, max_volume]
                        for value in values :
                            if value == None : value = "" # otherwise crash: "malloc(): invalid size (unsorted)"
                        verbose_csv_writer.writerow(values)

                    else :
                        print (file(file_path))
                except subprocess.CalledProcessError as error :
                    files_with_errors.append((file_path, error.returncode))

            print(len(file_paths), "files,", len(file_paths) - file_count,
                "errors in:", directory_path)
            if extension not in [".flac", ".mp3"] :
                if verbose : print(); continue
            if file_count :
                mean_average = mean_sum / file_count
                peak_average = peak_sum / file_count
                rate_average = rate_sum / file_count
                print("Album volumes: mean: %5.1f | %5.1f | %5.1f dB, peak: %5.1f | %5.1f | %5.1f dB      (%1.0f, %s)"
                    %(mean_average, mean_min, mean_max, peak_average, peak_min, peak_max, rate_average, rate_mode))
                album_mean_sum += mean_average
                album_mean_min = min(album_mean_min, mean_min)
                album_mean_max = max(album_mean_max, mean_max)
                album_peak_sum += peak_average
                album_peak_min = min(album_peak_min, peak_min)
                album_peak_max = max(album_peak_max, peak_max)
            if peak_max < threshold :
                albums_with_low_volume.append(
                    (directory_path, mean_sum / file_count, peak_min, peak_max))
            if rate_mode == "Mixed" : albums_with_mixed_mode.append((directory_path, rate_average))
            if rate_mixed and rate_mode == "CBR" :
                albums_with_mixed_constant_rate.append((directory_path, rate_average))
            if verbose : print()

            # Write values to csv file:
            values = [album_count, directory_path, file_count, rate_mode, int(rate_average),]
            for value in values :
                if value == None : value = "" # otherwise crash: "malloc(): invalid size (unsorted)"
            csv_writer.writerow(values)


    print()
    print("Directories total:     ", len(directory_paths))
    print("Albums with "+extension+" files:", album_count)
    if album_count :
        album_mean_average = album_mean_sum / album_count
        album_peak_average = album_peak_sum / album_count
        print("All albums volumes: mean: %5.1f | %5.1f | %5.1f dB, peak: %5.1f | %5.1f | %5.1f dB"
            %(album_mean_average, album_mean_min, album_mean_max, album_peak_average, album_peak_min, album_peak_max))
    if albums_with_low_volume :
        print(f"\nAlbums with low volume ({len(albums_with_low_volume)}):")
        for album, average_mean, peak_min, peak_max in albums_with_low_volume:
            print("%s\n"
                "    volumes: average mean | min max | max max : %5.1f | %5.1f | %5.1f dB"
                %(album, average_mean, peak_min, peak_max))
    if albums_with_mixed_mode :
        print(f"\nAlbums with mixed bit rate mode ({len(albums_with_mixed_mode)}):")
        for album, rate_average in albums_with_mixed_mode:
            print(f"{album} ==> {rate_average/1000:3.1f} kb/s")
    if albums_with_mixed_constant_rate :
        print(f"\nAlbums with mixed constant bit rate ({len(albums_with_mixed_constant_rate)}):")
        for album, rate_average in albums_with_mixed_constant_rate:
            print(f"{album} ==> {rate_average/1000:3.1f} kb/s")
    if files_without_bitrate :
        print(f"\n{extension} files without bit rate: ({len(files_without_bitrate)}):")
        for file_path in files_without_bitrate:
            print(file_path)
    if files_with_comment :
        print(f"\n{extension} files with comment: ({len(files_with_comment)}):")
        for file_path in files_with_comment:
            print(file_path)
    if files_with_notes :
        print(f"\n{extension} files with notes: ({len(files_with_notes)}):")
        for file_path in files_with_notes:
            print(file_path)
    if files_with_audio_comment :
        print(f"\n{extension} files with audio comment: ({len(files_with_audio_comment)}):")
        for file_path in files_with_audio_comment:
            print(file_path)
    if files_with_errors :
        print(f"\n{extension} files with errors: ({len(files_with_errors)}):")
        for file_path, returncode in files_with_errors:
            print(file_path, "==> return code:", returncode)


if __name__ == "__main__" :
    main()

Nur in folgendem Ordner taucht dann der Fehler auf (hundert andere Ordner laufen fehlerfrei durch):

$ ./volume-analysis.py "Ablage/Rick Wakeman" .mp3 -1.2 --verbose
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/01 Music Reincarnate, Part I_ The Warning (Introduction).mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.3 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/02 Music Reincarnate, Part I_ The Warning (Conclusion).mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.9 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/03 Music Reincarnate_ The Maker.mp3
malloc(): invalid size (unsorted)
Abgebrochen (Speicherabzug geschrieben)

Wenn ich dann in Zeile 106 den Kommentar wegnehme (um zu checken, wie weit das Programm noch kommt), also:

1
                    print(f" general comment: {general.comment}, audio comment: {audio.comment}, abcd: {audio.abcd},")

dann läuft es merkwürdigerweise fehlerfrei durch:

$ ./volume-analysis.py "Ablage/Rick Wakeman" .mp3 -1.2 --verbose
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/01 Music Reincarnate, Part I_ The Warning (Introduction).mp3
 general comment: None, audio comment: None, abcd: None,
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.3 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/02 Music Reincarnate, Part I_ The Warning (Conclusion).mp3
 general comment: None, audio comment: None, abcd: None,
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.9 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/03 Music Reincarnate_ The Maker.mp3
 general comment: None, audio comment: None, abcd: None,
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -15.6 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/04 Music Reincarnate, Part III_ The Spaceman.mp3
 general comment: None, audio comment: None, abcd: None,
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.6 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/05 Music Reincarnate_ The Realisation.mp3
 general comment: None, audio comment: None, abcd: None,
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -14.9 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/06 Music Reincarnate, Part V_ The Reaper.mp3
 general comment: None, audio comment: None, abcd: None,
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -14.6 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/07 The Prisoner.mp3
 general comment: None, audio comment: None, abcd: None,
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.6 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/08 The Lost Cycle.mp3
 general comment: None, audio comment: None, abcd: None,
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.8 dB, peak volume:   0.0 dB      (320000, CBR)
8 files, 0 errors in: Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection
Album volumes: mean: -14.2 | -15.6 | -13.3 dB, peak:   0.0 |   0.0 |   0.0 dB      (320000, CBR)


Directories total:      5
Albums with .mp3 files: 1
All albums volumes: mean: -14.2 | -15.6 | -13.3 dB, peak:   0.0 |   0.0 |   0.0 dB

Der Crash scheint also etwas mit der print-Funktion zu tun zu haben.

Mit dem mediainfo-Bug hat es diesmal wohl nichts zu tun, denn folgendes läuft fehlerfrei durch:

$ mediainfo "Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/"*.mp3
$ mediainfo "Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/03 Music Reincarnate_ The Maker.mp3"

Nun habe ich den Ordnerpfad mal eine Ebene tiefer angegeben, also Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection ... dann läuft das Programm wieder vollständig durch.

Danach habe ich wieder mit dem kürzeren Ordnerpfad probiert, also Ablage/Rick Wakeman ... diesmal läuft das Programm dann merkwürdigerweise doch wieder vollständig durch.

Leite ich die Ausgabe in eine Datei um mit " > Analysis.log" oder " | tee Analysis.log", crashed das Programm wieder.

Der Crash ist also nur bedingt unter gleichen Bedingungen reproduzierbar. Sehr merkwürdig ! Hat jemand eine Idee, wie ich dem Problem auf die Spur kommen kann?

EDIT: Jetzt, 10 Min. später crashed es wieder mit Ablage/Rick Wakeman

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4784

Wohnort: Berlin

Ich würde das mal mit Valgrind laufen lassen und schauen ob man damit der Quelle näher kommt.

Irgendwelcher Code scheint in den RAM zu schreiben wo er nicht sollte und (zer)stört dabei die Verwaltungsinformationen von malloc()/free().

UlfZibis

(Themenstarter)

Anmeldungsdatum:
13. Juli 2011

Beiträge: 3440

Wohnort: Köln

Marc_BlackJack_Rintsch schrieb:

Irgendwelcher Code scheint in den RAM zu schreiben wo er nicht sollte und (zer)stört dabei die Verwaltungsinformationen von malloc()/free().

Klingt plausibel 💡

Ich würde das mal mit Valgrind laufen lassen und schauen ob man damit der Quelle näher kommt.

Entschuldige, wenn ich so blöd frage, aber wie geht das denn?

Falls es doch mit der mediainfo Bibliothek zu tun hat, wie könnte ich das in Python abfangen, damit das Programm weiterlaufen kann?

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4784

Wohnort: Berlin

Einfach statt programmname --optionen … das ganze mit valgrind programmname --optionen … starten. Dann klemmt sich Valgrind zwischen das Programm und die Speicherverwaltungsfunktionen und bekommt hoffentlich den Zugriff mit und protokolliert den so, dass wir sehen können von wo aus der kommt.

Solche Fehler kann man nicht abfangen. Nicht nur nicht in Python. Was soll man denn machen wenn die Informationen, welche die C-Laufzeitbibliothek zur Verwaltung des Speichers benötigt, kaputt sind? Und das fällt hier ja anscheinend nur zufällig auf, der betroffene Code kann ja auch wenn das Programm durch läuft, irgendwelche Daten überschreiben.

UlfZibis

(Themenstarter)

Anmeldungsdatum:
13. Juli 2011

Beiträge: 3440

Wohnort: Köln

Marc_BlackJack_Rintsch schrieb:

Einfach statt programmname --optionen … das ganze mit valgrind programmname --optionen … starten. Dann klemmt sich Valgrind zwischen das Programm und die Speicherverwaltungsfunktionen und bekommt hoffentlich den Zugriff mit und protokolliert den so, dass wir sehen können von wo aus der kommt.

Ach so einfach ist das. Dann also mal los:

$ valgrind ./volume-analysis_bug.py "Ablage/Rick Wakeman" .mp3 -1.2 --verbose
==489357== Memcheck, a memory error detector
==489357== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==489357== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==489357== Command: ./volume-analysis_bug.py Ablage/Rick\ Wakeman .mp3 -1.2 --verbose
==489357== 
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/01 Music Reincarnate, Part I_ The Warning (Introduction).mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.3 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/02 Music Reincarnate, Part I_ The Warning (Conclusion).mp3
malloc(): invalid size (unsorted)
Abgebrochen (Speicherabzug geschrieben)

Diesmal also Crash schon beim 2. statt wie sonst beim 3. Titel. Ohne valgrind lief es kurz vorher aber mal wieder fehlerfrei.

Ich denke mal, mit der obigen Ausgabe ist erst mal nicht viel anzufangen. Ich versuche mich mal schlau zu machen, aber vielleicht hast Du ja auch gute Hinweise.

Solche Fehler kann man nicht abfangen. Nicht nur nicht in Python. Was soll man denn machen wenn die Informationen, welche die C-Laufzeitbibliothek zur Verwaltung des Speichers benötigt, kaputt sind?

Dachte ich mir schon. Ginge nur, wenn ich mediainfo wieder per subprocess.run() nutzen würde. Damit hatte ich die malloc()-Meldung auch und mein Programm lief mit dem nächsten Titel schön weiter. Das veranlasste mich, den erwähnten Bug auf LaunchPad zu posten. Zu meiner Überraschung bekam ich da schnell eine Reaktion mit dem Verweis auf die neueste Version, wo der Fehler behoben wurde, Seitdem trat der Fehler erheblich seltener auf.

UlfZibis

(Themenstarter)

Anmeldungsdatum:
13. Juli 2011

Beiträge: 3440

Wohnort: Köln

Nun also noch mal mit den hier empfohlenen Parametern:

$ G_SLICE=always-malloc G_DEBUG=gc-friendly  valgrind -v --tool=memcheck --leak-check=full --num-callers=40 --log-file=valgrind.log ./volume-analysis_bug.py "Ablage/Rick Wakeman" .mp3 -1.2 --verbose
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/01 Music Reincarnate, Part I_ The Warning (Introduction).mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.3 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/02 Music Reincarnate, Part I_ The Warning (Conclusion).mp3
malloc(): invalid size (unsorted)
Abgebrochen (Speicherabzug geschrieben)

Ergebnis in valgrind.log:

==491080== Memcheck, a memory error detector
==491080== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==491080== Using Valgrind-3.22.0-bd4db67b1d-20231031 and LibVEX; rerun with -h for copyright info
==491080== Command: ./volume-analysis_bug.py Ablage/Rick\ Wakeman .mp3 -1.2 --verbose
==491080== Parent PID: 101433
==491080== 
--491080-- 
--491080-- Valgrind options:
--491080--    -v
--491080--    --tool=memcheck
--491080--    --leak-check=full
--491080--    --num-callers=40
--491080--    --log-file=valgrind.log
--491080-- Contents of /proc/version:
--491080--   Linux version 6.8.0-79-generic (buildd@lcy02-amd64-049) (x86_64-linux-gnu-gcc-13 (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0, GNU ld (GNU Binutils for Ubuntu) 2.42) #79-Ubuntu SMP PREEMPT_DYNAMIC Tue Aug 12 14:42:46 UTC 2025
--491080-- 
--491080-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-lzcnt-rdtscp-sse3-ssse3-avx-avx2-bmi-f16c-rdrand
--491080-- Page sizes: currently 4096, max supported 4096
--491080-- Valgrind library directory: /usr/libexec/valgrind
--491080-- Reading syms from /usr/bin/env
--491080-- Reading syms from /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
--491080--   Considering /usr/lib/debug/.build-id/28/1ac1521b4102509b1c7ac7004db7c1efb81796.debug ..
--491080--   .. build-id is valid
--491080-- Reading syms from /usr/libexec/valgrind/memcheck-amd64-linux
--491080--    object doesn't have a dynamic symbol table
--491080-- Scheduler: using generic scheduler lock implementation.
--491080-- Reading suppressions file: /usr/libexec/valgrind/default.supp
==491080== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-491080-by-ich-on-???
==491080== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-491080-by-ich-on-???
==491080== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-491080-by-ich-on-???
==491080== 
==491080== TO CONTROL THIS PROCESS USING vgdb (which you probably
==491080== don't want to do, unless you know exactly what you're doing,
==491080== or are doing some strange experiment):
==491080==   /usr/bin/vgdb --pid=491080 ...command...
==491080== 
==491080== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==491080==   /path/to/gdb ./volume-analysis_bug.py
==491080== and then give GDB the following command
==491080==   target remote | /usr/bin/vgdb --pid=491080
==491080== --pid is optional if only one valgrind process is running
==491080== 
--491080-- REDIR: 0x4028b00 (ld-linux-x86-64.so.2:strlen) redirected to 0x580c2e1a (???)
--491080-- REDIR: 0x40272b0 (ld-linux-x86-64.so.2:index) redirected to 0x580c2e34 (???)
--491080-- Reading syms from /usr/libexec/valgrind/vgpreload_core-amd64-linux.so
--491080-- Reading syms from /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so
==491080== WARNING: new redirection conflicts with existing -- ignoring it
--491080--     old: 0x04028b00 (strlen              ) R-> (0000.0) 0x580c2e1a ???
--491080--     new: 0x04028b00 (strlen              ) R-> (2007.0) 0x0484f340 strlen
--491080-- REDIR: 0x40274e0 (ld-linux-x86-64.so.2:strcmp) redirected to 0x4850460 (strcmp)
--491080-- REDIR: 0x4026910 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4853cd0 (mempcpy)
--491080-- Reading syms from /usr/lib/x86_64-linux-gnu/libc.so.6
--491080--   Considering /usr/lib/debug/.build-id/28/2c2c16e7b6600b0b22ea0c99010d2795752b5f.debug ..
--491080--   .. build-id is valid
--491080-- REDIR: 0x4028ca0 (ld-linux-x86-64.so.2:strncmp) redirected to 0x484fc90 (strncmp)
--491080-- REDIR: 0x492d050 (libc.so.6:strnlen) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492d0e0 (libc.so.6:strpbrk) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492b1a0 (libc.so.6:strcmp) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x49443b0 (libc.so.6:wcsnlen) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492a290 (libc.so.6:memset) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x4943b20 (libc.so.6:wcslen) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x49af3c0 (libc.so.6:__memcpy_chk) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492a200 (libc.so.6:memrchr) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x4944350 (libc.so.6:wcsncpy) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x4929720 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x49428e0 (libc.so.6:wcschr) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492b090 (libc.so.6:index) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492d110 (libc.so.6:rindex) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x4942990 (libc.so.6:wcscmp) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492a4b0 (libc.so.6:stpncpy) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x4950eb0 (libc.so.6:wmemchr) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492cef0 (libc.so.6:strncmp) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492a510 (libc.so.6:strcasecmp) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492c310 (libc.so.6:strcspn) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x49438f0 (libc.so.6:wcscpy) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492b020 (libc.so.6:strcat) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492cdf0 (libc.so.6:strncasecmp_l) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492b110 (libc.so.6:strchrnul) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x4929630 (libc.so.6:bcmp) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492c2a0 (libc.so.6:strcpy) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492a5b0 (libc.so.6:strcasecmp_l) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492ccc0 (libc.so.6:strlen) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492cf90 (libc.so.6:strncpy) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x4950f30 (libc.so.6:wmemcmp) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x49af4e0 (libc.so.6:__memmove_chk) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
==491080== WARNING: new redirection conflicts with existing -- ignoring it
--491080--     old: 0x04a009d0 (__memcpy_chk_avx_una) R-> (2030.0) 0x04853dd0 __memcpy_chk
--491080--     new: 0x04a009d0 (__memcpy_chk_avx_una) R-> (2024.0) 0x04853740 __memmove_chk
--491080-- REDIR: 0x492a440 (libc.so.6:stpcpy) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x4929fc0 (libc.so.6:memmove) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
==491080== Preferring higher priority redirection:
--491080--     old: 0x04a00a00 (__memcpy_avx_unalign) R-> (2018.0) 0x04851580 __memcpy_avx_unaligned_erms
--491080--     new: 0x04a00a00 (__memcpy_avx_unalign) R-> (2018.1) 0x04852d60 memmove
--491080-- REDIR: 0x49295b0 (libc.so.6:memchr) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492d2e0 (libc.so.6:strspn) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492a0e0 (libc.so.6:mempcpy) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x492cd50 (libc.so.6:strncasecmp) redirected to 0x483d1c0 (_vgnU_ifunc_wrapper)
--491080-- REDIR: 0x4a055f0 (libc.so.6:__strrchr_avx2) redirected to 0x484ed20 (rindex)
--491080-- REDIR: 0x4a04820 (libc.so.6:__strncmp_avx2) redirected to 0x484fab0 (strncmp)
--491080-- REDIR: 0x4a02f90 (libc.so.6:__strcmp_avx2) redirected to 0x4850360 (strcmp)
--491080-- REDIR: 0x4a03740 (libc.so.6:__strlen_avx2) redirected to 0x484f220 (strlen)
--491080-- REDIR: 0x4a02b60 (libc.so.6:__strchr_avx2) redirected to 0x484ef00 (index)
--491080-- REDIR: 0x4a00000 (libc.so.6:__memchr_avx2) redirected to 0x48504e0 (memchr)
--491080-- REDIR: 0x4a02da0 (libc.so.6:__strchrnul_avx2) redirected to 0x48537b0 (strchrnul)
--491080-- REDIR: 0x4925650 (libc.so.6:malloc) redirected to 0x48467b0 (malloc)
--491080-- REDIR: 0x4a009c0 (libc.so.6:__mempcpy_avx_unaligned_erms) redirected to 0x48538d0 (mempcpy)
--491080-- REDIR: 0x4a00a00 (libc.so.6:__memcpy_avx_unaligned_erms) redirected to 0x4852d60 (memmove)
--491080-- REDIR: 0x4925d30 (libc.so.6:free) redirected to 0x4849820 (free)
--491080-- REDIR: 0x4a009d0 (libc.so.6:__memcpy_chk_avx_unaligned_erms) redirected to 0x4853dd0 (__memcpy_chk)
--491080-- REDIR: 0x49267a0 (libc.so.6:calloc) redirected to 0x484d8a0 (calloc)
--491080-- REDIR: 0x4a05320 (libc.so.6:__strnlen_avx2) redirected to 0x484f1c0 (strnlen)

Tja, wo könnte das Problem nun liegen?

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4784

Wohnort: Berlin

Hm, viellleicht mal Python direkt starten, also valgrind python3 volume-analysis_bug.py "Ablage/Rick Wakeman" .mp3 -1.2 --verbose.

UlfZibis

(Themenstarter)

Anmeldungsdatum:
13. Juli 2011

Beiträge: 3440

Wohnort: Köln

Marc_BlackJack_Rintsch schrieb:

Hm,

In dem Log sieht man allerdings Warnings, dass da Speicher wohl mehrfach benutzt wird. das könnte doch die Ursache sein. Ist nur die Frage, wie man rauskriegt, wo und in welchem Code das passiert.

viellleicht mal Python direkt starten, also valgrind python3 volume-analysis_bug.py "Ablage/Rick Wakeman" .mp3 -1.2 --verbose.

Damit läuft es fehlerfrei durch alle 8 Titel durch.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4784

Wohnort: Berlin

Wirklich fehlerfrei oder nur ohne Absturz? Nicht jeder von valgrind gemeldete Speicherzugriffsfehler führt auch zum Absturz.

Dieses kleine Testprogramm beispielsweise, …

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int i;
    char *a, *b;

    a = malloc(1);
    for (i = 0; i < (1 << 30); ++i) {
        // printf("%d\n", i);
        a[i] = 42;
        b = malloc(1);
        free(b);
    }
    return 0;
}

…das direkt ausgeführt quasi sofort zu einem Absturz führt, …

$ gcc test_c.c
$ ./a.out 
munmap_chunk(): invalid pointer
Aborted (core dumped)

…läuft unter valgrind ewig, also bis ich es mit Strg+C abbreche. Aber es gibt den ersten ungültigen Schreibzugriff aus:

$ valgrind ./a.out 
==2620== Memcheck, a memory error detector
==2620== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2620== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2620== Command: ./a.out
==2620== 
==2620== Invalid write of size 1
==2620==    at 0x1086B6: main (in /home/bj/a.out)
==2620==  Address 0x5859041 is 0 bytes after a block of size 1 alloc'd
==2620==    at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2620==    by 0x10869B: main (in /home/bj/a.out)
==2620== 
^C
…

UlfZibis

(Themenstarter)

Anmeldungsdatum:
13. Juli 2011

Beiträge: 3440

Wohnort: Köln

Marc_BlackJack_Rintsch schrieb:

Wirklich fehlerfrei oder nur ohne Absturz?

Ich denke, auch fehlerfrei:

$ valgrind python3 volume-analysis_bug.py "Ablage/Rick Wakeman" .mp3 -1.2 --verbose
==621709== Memcheck, a memory error detector
==621709== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==621709== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==621709== Command: python3 volume-analysis_bug.py Ablage/Rick\ Wakeman .mp3 -1.2 --verbose
==621709== 
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/01 Music Reincarnate, Part I_ The Warning (Introduction).mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.3 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/02 Music Reincarnate, Part I_ The Warning (Conclusion).mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.9 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/03 Music Reincarnate_ The Maker.mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -15.6 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/04 Music Reincarnate, Part III_ The Spaceman.mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.6 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/05 Music Reincarnate_ The Realisation.mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -14.9 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/06 Music Reincarnate, Part V_ The Reaper.mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -14.6 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/07 The Prisoner.mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.6 dB, peak volume:   0.0 dB      (320000, CBR)
Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection/08 The Lost Cycle.mp3
  Format=MPEG Audio, Format settings=Joint stereo, Format profile=Layer 3, Channel(s)=2, Bit rate mode=CBR, Bit rate=320000, Sampling rate=44100, Bit depth=None
  mean volume: -13.8 dB, peak volume:   0.0 dB      (320000, CBR)
8 files, 0 errors in: Ablage/Rick Wakeman/Rick Wakeman - No Earthly Connection
Album volumes: mean: -14.2 | -15.6 | -13.3 dB, peak:   0.0 |   0.0 |   0.0 dB      (320000, CBR)


Directories total:      5
Albums with .mp3 files: 1
All albums volumes: mean: -14.2 | -15.6 | -13.3 dB, peak:   0.0 |   0.0 |   0.0 dB
==621709== 
==621709== HEAP SUMMARY:
==621709==     in use at exit: 565,945 bytes in 190 blocks
==621709==   total heap usage: 111,315 allocs, 111,125 frees, 597,500,004 bytes allocated
==621709== 
==621709== LEAK SUMMARY:
==621709==    definitely lost: 0 bytes in 0 blocks
==621709==    indirectly lost: 0 bytes in 0 blocks
==621709==      possibly lost: 0 bytes in 0 blocks
==621709==    still reachable: 565,945 bytes in 190 blocks
==621709==         suppressed: 0 bytes in 0 blocks
==621709== Rerun with --leak-check=full to see details of leaked memory
==621709== 
==621709== For lists of detected and suppressed errors, rerun with: -s
==621709== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Dieses kleine Testprogramm beispielsweise, … …das direkt ausgeführt quasi sofort zu einem Absturz führt, … …läuft unter valgrind ewig, also bis ich es mit Strg+C abbreche. Aber es gibt den ersten ungültigen Schreibzugriff aus:

Schönes Beispiel.

Bei mir kommen ja nur Warnings, keine Errors. Wie ist denn das zu bewerten?

Von Launchpad wurde ich aufgefordert, den Bug nun "upstream" behandeln zu lassen: MediaArea/MediaInfoLib/issues/2400

snafu1

Avatar von snafu1

Anmeldungsdatum:
5. September 2007

Beiträge: 2149

Wohnort: Gelsenkirchen

Ich weiß nicht ob es hilft, aber die Pandas Doku empfiehlt hier, dass man zum Testen von C-Extensions die Umgebungsvariable für das verwendete malloc anpassen und für valgrind ein paar zusätzliche Optionen mitgeben sollte:

1
PYTHONMALLOC=malloc valgrind --leak-check=yes --track-origins=yes --log-file=valgrind-log.txt python -m pytest <path_to_a_test>

Vielleicht willst du das mal ausprobieren. Hinter python bzw. python3 natürlich dein Skript setzen.

UlfZibis

(Themenstarter)

Anmeldungsdatum:
13. Juli 2011

Beiträge: 3440

Wohnort: Köln

snafu1 schrieb:

Ich weiß nicht ob es hilft, aber die Pandas Doku empfiehlt ...

Leider blicke ich bei valgrind zu wenig durch, aber ich habe den Tipp mal weitergegeben.
Dort scheint man aktuell auch schon auf einer heißen Spur zu sein.

Sehr lobenswert, dass die Entwickler von MediaInfo so kurzfristig und fleißig reagieren.

snafu1

Avatar von snafu1

Anmeldungsdatum:
5. September 2007

Beiträge: 2149

Wohnort: Gelsenkirchen

UlfZibis schrieb:

Leider blicke ich bei valgrind zu wenig durch, aber ich habe den Tipp mal weitergegeben.

Naja, der Tipp war eigentlich für dich gedacht. Die Entwickler fahren da ganz andere Kaliber auf. 😉

Jedenfalls lesen sich die dortigen Äußerungen für mich, dass ein Linux-spezifisches Problem besteht, mutmaßlich in Zusammenhang mit dem AVX-Befehlssatz. Da werden wir hier im Forum wohl nicht viel weiterhelfen können, denn das ist ja kein Anwenderfehler von dir, sondern offenbar ein Bug in einer tieferliegenden Bibliothek. Ich schätze, da wird letztlich ein Workaround von den Entwicklern der MediaInfoLib im Code bereitgestellt.

UlfZibis

(Themenstarter)

Anmeldungsdatum:
13. Juli 2011

Beiträge: 3440

Wohnort: Köln

Der Fehler wurde behoben. Danke an das Team von MediaInfo: MediaArea/MediaInfoLib/issues/2400

Antworten |