valgrind – Adres – is 0 bytes na een blok van grootte 8 toegewezen

Ten eerste weet ik dat er vergelijkbarevragen zijn gesteld. Ik zou echter graag een meer algemene, eenvoudige vraag willen hebben met echt primitieve C-gegevenstypen. Dus hier is het.

In main.croep ik een functie aan om die string te vullen:

int
main (int argc, char *argv[]){
    char *host = NULL ;
    char *database ;
    char *collection_name;
    char *filename = ""; 
    char *fields = NULL;
    char *query = NULL;
    ...
    get_options(argc, argv, &host, &database, &collection_name, &filename, 
                &fields, &query, &aggregation);

Inside get_options:

if (*filename == NULL ) {
   *filename = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+4);
    strcpy(*filename, *collection_name);
    strcat(*filename, ".tde");  # line 69 
}

Mijn programma werkt prima, maar dan zegt Valgrind dat ik het verkeerd doe:

==8608== Memcheck, a memory error detector
==8608== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==8608== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==8608== Command: ./coll2tde -h localhost -d test -c test
==8608== 
==8608== Invalid write of size 1
==8608==    at 0x403BE2: get_options (coll2tde.c:69)
==8608==    by 0x402213: main (coll2tde.c:92)
==8608==  Address 0xa2edd18 is 0 bytes after a block of size 8 alloc'd
==8608==    at 0x4C28BED: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8608==    by 0x4C28D6F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8608==    by 0x403BBC: get_options (coll2tde.c:67)
==8608==    by 0x402213: main (coll2tde.c:92)

Kun je de fout uitleggen Address 0xa2edd18 is 0 bytes after a block of size 8 alloc'd?
Hoe kan ik dit probleem oplossen?


Antwoord 1, autoriteit 100%

strcpyvoegt een null-terminatorteken toe '\0'. Je bent vergeten er ruimte voor toe te wijzen:

*filename = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+5);

Je moet ruimte toevoegen voor 5 tekens: 4 voor het achtervoegsel ".tde"en nog een voor de terminator '\0'. Uw huidige code wijst slechts 4 toe, dus de laatste keer schrijven wordt gedaan in de ruimte onmiddellijk na het blok dat u hebt toegewezen voor de nieuwe bestandsnaam (d.w.z. 0 bytes erna).

Opmerking:Uw code heeft een veelvoorkomend probleem: het wijst de resultaten van reallocrechtstreeks toe aan een aanwijzer die opnieuw wordt toegewezen. Dit is prima wanneer reallocsuccesvol is, maar creëert een geheugenlek wanneer het mislukt. Om deze fout op te lossen, moet het resultaat van reallocin een aparte variabele worden opgeslagen en moet worden gecontroleerd op NULLvoordat de waarde weer wordt toegewezen aan *filename:

char *tmp = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+5);
if (tmp != NULL) {
    *filename = tmp;
} else {
    // Do something about the failed allocation
}

Rechtstreeks toewijzen aan *filenamecreëert een geheugenlek, omdat de aanwijzer waarnaar de *filenamehieronder verwijst, bij een fout wordt overschreven en niet meer kan worden hersteld.


Antwoord 2, autoriteit 2%

Ik kreeg zojuist dit bericht omdat ik een klasse had gewijzigd (een veld had toegevoegd, dus de grootte ervan had gewijzigd) en niet alle bronnen die de header bevatten opnieuw had opgebouwd. Dus sommige modules probeerden nog steeds het oude formaat te gebruiken.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

two × two =

Other episodes