Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C] malloc problemen, strings worden random veranderd

Pagina: 1
Acties:
  • 131 views sinds 30-01-2008
  • Reageer

  • The__Virus
  • Registratie: Januari 2005
  • Laatst online: 27-11 09:56
Ik heb een probleem waar ik na 3 uur zoeken en testen niet uitkom. Ik moet een hashtable maken met daarin willekeurige zinnen. Nu reserveer ik eerst ruimte voor de grootte van de hashtable (op dit moment 100), daarna, wanneer een zin wordt toegevoegd, een realloc van de tabel van de pointers bij de betreffende hash (meerdere strings per hash, dus wordt steeds groter) en dan een voeg ik de zin toe met een malloc aan die zin.

Echter, het probleem is dat na het toevoegen van een willekeurig aantal zinnen, er zinnen worden veranderd. De geheugenadressen in de hashtable blijven hetzelfde (ondervonden na testen), maar de zin veranderd in willekeurige tekens. Dit blijft een tijdje zo (tijdens het toevoegen), totdat de reeks weer anders wordt (weer willekeurige tekens). Ik heb dit voor een paar verschillende zinnen getest en kom er echt niet meer uit: het is niet bij een vast aantal (bij zelfde zin is het wel telkens bij bij hetzelfde aantal zinnen dat toe is gevoegd, maar de count (aantal zinnen in de hashgroep) is dan niet veranderd ofzo).

Heb wel een beetje dirty manier om de count van elke hash bij te houden, maar het werkt wel.

Beetje lastig uit te leggen, nog lastiger te vinden, ik hoop dat jullie mij wat verder kunnen helpen. Het is mijn eerste keer met malloc dus ik ben nog vrij noobie.

Iig alvast bedankt voor de moeite!

Relevante code:

Zie een latere post.

Nogmaals, de zinnen worden er daadwerkelijk goed ingezet, in de console heb ik de hele tijd één zin laten uitlezen en die blijft telkens hetzelfde, tot op bepaalde hoogte, dan verandert de zin dus in willekeurige tekens. Ik ben er een beetje wanhopig van geworden, hoop dat jullie mij verder kunnen helpen! Meer code op verzoek :).

[ Voor 61% gewijzigd door The__Virus op 29-10-2007 08:49 ]


Verwijderd

't Zal je probleem niet direct oplossen, maar aangezien je aangeeft dat je voor het eerst malloc() en consorten gebruikt, lijkt het me dit een nuttige tip: nadat je geheugen gealloceerd hebt met malloc/calloc/realloc, dien je het vrij te geven met free() zodra je ermee klaar bent!

Memory leaks zijn niet leuk... :)

  • The__Virus
  • Registratie: Januari 2005
  • Laatst online: 27-11 09:56
Dat zijn mijn andere functies, die zijn alleen niet relevant ;). Alleen die werken dus niet, omdat die zinnen veranderen: er wordt andere data op dat geheugen geschreven en een free geeft dus een keiharde memory access error. De geheugenlocaties veranderen niet, maar iets of iemand schrijft er dus gewoon bruutweg overheen...

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Mijn C is niet zo best (en ik krijg de code niet 1-2-3 gecompileerd), maar zo te zien retourneert je random_sentence functie geen \0 getermineerde strings, dus dat zal sowieso voor problemen zorgen?

Wie trösten wir uns, die Mörder aller Mörder?


  • Orion84
  • Registratie: April 2002
  • Nu online

Orion84

Admin General Chat / Wonen & Mobiliteit

Fotogenie(k)?

Confusion schreef op zondag 28 oktober 2007 @ 13:06:
Mijn C is niet zo best (en ik krijg de code niet 1-2-3 gecompileerd), maar zo te zien retourneert je random_sentence functie geen \0 getermineerde strings, dus dat zal sowieso voor problemen zorgen?
sentence[strlen(sentence)-1]=0; << daar wordt de laatste byte overschreven met 0, waardoor hij dus van de overtollige spatie verlost is denk ik en de string een byte eerder beëindigd wordt?

Mgoed, even mijn kijk op dit alles:

Nou, je genereert dus een of andere zin die je in sentence stopt, daarna alloceer je geheugen voor sentenceaddress en kopieer je daar de string naartoe.
Maar voor sentence zelf alloceer je nooit iets, dus als je daar dingen naartoe gaat schrijven schrijf je naar ongealloceerd geheugen, en dat gaat dus op een gegeven moment geheugenlocaties zijn die je al in gebruik had ;)

Althans, je alloceert er 1 byte geheugen voor door "" te assignen. Waarmee dus alleen een afsluitende 0 wordt opgeslagen.
Of vergroten de functies waarmee je sentence op bouwt de gealloceerde ruimte zelf al netjes ofzo? ben hier verder ook niet extreem in thuis, maar vind het wel een beetje vreemde constructie zo?

(strlen(sentence)+1)*sizeof(char *) << dat klopt volgens mij ook niet helemaal, als ik dat met mijn gebrekkige C kennis lees dan alloceer je "het aantal tekens in de string" * "de afmetingen voor een char pointer". terwijl je de afmetingen van een char moet hebben :?
Wat hoe dan ook gewoon een byte is, waardoor je dat stuk ook gewoon weg kan laten?

Verder snap ik sowieso niet waarom je niet gewoon sentence returnt, aangezien dat gewoon hetzelfde is :?


Mgoed, correct me if i'm wrong, het ziet er vreemd uit in mijn ogen, maar dat zegt niet alles, aangezien ik zelf nauwelijks verstand heb van C. Dus wellicht dat C er gewoon vreemd uit hoort te zien :+

Edit: ook even geprobeerd te compilen. Een van de problemen die daar ook nog naar voren kwam is hier:
code:
1
printf("\n\n\%s in hash %d, sentencecount: %d, s: %d\n",hashtable[0][1],0, sentencecount,&hashtable[0][1]);

Daar staat een \ teveel, waardoor de %s genegeerd wordt en de %d het eerste argument probeert te lezen, terwijl dat geen int is.

Verder output van gcc -Wall:
code:
1
2
3
4
5
6
7
8
9
10
11
probleem.c: In function 'random_sentence':
probleem.c:29: error: too many arguments to function 'random'
probleem.c:34: error: too many arguments to function 'random'
probleem.c: At top level:
probleem.c:45: warning: return type of 'main' is not 'int'
probleem.c: In function 'main':
probleem.c:113: warning: implicit declaration of function 'itoa'
probleem.c:114: warning: format '%d' expects type 'int', but argument 5 has type                                                                                'char **'
probleem.c:87: warning: unused variable 'found'
probleem.c:71: warning: unused variable 'str'
probleem.c:70: warning: unused variable 'randomstring'

Maar dat heeft deels vermoedelijk te maken met dat we hier maar een deel van code te zien hebben gekregen?

[ Voor 100% gewijzigd door Orion84 op 28-10-2007 13:36 ]

The problem with common sense is that it's not all that common. | LinkedIn | Flickr


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

C:
1
2
3
4
5
6
7
8
        hashtable = (char ***) malloc(HASHSIZE * sizeof(char**)); 
        printf("-> Building dictionary index. Please wait...\n"); 
        for(i=0;i<HASHSIZE;i++) 
        {
                hashtable[i] = (char **) calloc(1,sizeof(char **)); 
                hashtable[i][0] = (char *) calloc(1,sizeof(char *)); 
                strcpy(hashtable[i][0], "0"); 
        }

Dit klopt niet helemaal. De eerste doe je goed (hashtable = malloc(...)), maar voor de elementen binnen die hashtable ga je de fout in. Je kunt het al zien als je de malloc voor hashtable en die voor hashtable[i] vergelijkt. In beide gevallen alloceer je een aantal char**'s. Hashtable is idd een array van char**, maar hashtable[i] is een array van char* en hashtable[i][j] is een array van char. Nou gaat dit toevallig niet fout omdat sizeof("0") < sizeof(char*), maar voor hashtable[i][0] moet je dus strlen("0") + 1 bytes alloceren.

Orion84 haalde het al aan: in random_sentence() reserveer je niet genoeg ruimte voor sentence. Sterker nog, je reserveert helemaal geen ruimte, want naar "" mag je niet schrijven (en die is bovendien maar 1 byte lang). Zorg dus dat sentence genoeg bytes bevat om alle strings in achter elkaar te plakken, inclusief de trailing \0.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • The__Virus
  • Registratie: Januari 2005
  • Laatst online: 27-11 09:56
Orion84 schreef op zondag 28 oktober 2007 @ 13:09:
[...]

sentence[strlen(sentence)-1]=0; << daar wordt de laatste byte overschreven met 0, waardoor hij dus van de overtollige spatie verlost is denk ik en de string een byte eerder beëindigd wordt?
Klopt inderdaad. Liep tegen het probleem aan dus even snel opgelost.
Mgoed, even mijn kijk op dit alles:

Nou, je genereert dus een of andere zin die je in sentence stopt, daarna alloceer je geheugen voor sentenceaddress en kopieer je daar de string naartoe.
Maar voor sentence zelf alloceer je nooit iets, dus als je daar dingen naartoe gaat schrijven schrijf je naar ongealloceerd geheugen, en dat gaat dus op een gegeven moment geheugenlocaties zijn die je al in gebruik had ;)

Althans, je alloceert er 1 byte geheugen voor door "" te assignen. Waarmee dus alleen een afsluitende 0 wordt opgeslagen.
Of vergroten de functies waarmee je sentence op bouwt de gealloceerde ruimte zelf al netjes ofzo? ben hier verder ook niet extreem in thuis, maar vind het wel een beetje vreemde constructie zo?
Is inderdaad niet zo. Heb het al veranderd naar char sentence[200], want jullie hebben idd helemaal gelijk.
(strlen(sentence)+1)*sizeof(char *) << dat klopt volgens mij ook niet helemaal, als ik dat met mijn gebrekkige C kennis lees dan alloceer je "het aantal tekens in de string" * "de afmetingen voor een char pointer". terwijl je de afmetingen van een char moet hebben :?
Wat hoe dan ook gewoon een byte is, waardoor je dat stuk ook gewoon weg kan laten?
Iig niet te weinig gereserveerd :+. Ook aangepast. Heb het verkeerd gedaan door de gedachte dat een string een char* is :P.
Verder snap ik sowieso niet waarom je niet gewoon sentence returnt, aangezien dat gewoon hetzelfde is :?
Dan zou ik sentence moeten mallocen toch? Ik heb dat een keer verwisseld, om te kijken of daar de fout zat (mallocen in main i.p.v. random_sentence() ). Maar dat is niet fout nu meer geloof ik.
Mgoed, correct me if i'm wrong, het ziet er vreemd uit in mijn ogen, maar dat zegt niet alles, aangezien ik zelf nauwelijks verstand heb van C. Dus wellicht dat C er gewoon vreemd uit hoort te zien :+

Edit: ook even geprobeerd te compilen. Een van de problemen die daar ook nog naar voren kwam is hier:
code:
1
printf("\n\n\%s in hash %d, sentencecount: %d, s: %d\n",hashtable[0][1],0, sentencecount,&hashtable[0][1]);

Daar staat een \ teveel, waardoor de %s genegeerd wordt en de %d het eerste argument probeert te lezen, terwijl dat geen int is.
Klopt als een bus, kwam ik ook achter na dit posten. Kwam door het proberen te vinden van de fout, allemaal dingen geprint om te kijken waar het fout gaat ;).
Verder output van gcc -Wall:
code:
1
2
3
4
5
6
7
8
9
10
11
probleem.c: In function 'random_sentence':
probleem.c:29: error: too many arguments to function 'random'
probleem.c:34: error: too many arguments to function 'random'
probleem.c: At top level:
probleem.c:45: warning: return type of 'main' is not 'int'
probleem.c: In function 'main':
probleem.c:113: warning: implicit declaration of function 'itoa'
probleem.c:114: warning: format '%d' expects type 'int', but argument 5 has type                                                                                'char **'
probleem.c:87: warning: unused variable 'found'
probleem.c:71: warning: unused variable 'str'
probleem.c:70: warning: unused variable 'randomstring'

Maar dat heeft deels vermoedelijk te maken met dat we hier maar een deel van code te zien hebben gekregen?
Klopt idd. Ik heb Borland, maar een paar dingen snap ik van jouw compiler niet:
- probleem.c:34: error: too many arguments to function 'random'.
- probleem.c: At top level:
probleem.c:45: warning: return type of 'main' is not 'int'
probleem.c: In function 'main':
Main is toch altijd void en niet int?

@.oisyn: heb het veranderd, bedankt voor je input! ;) Heb het veranderd.

Alleen dan nog één vraagje: als ik 'char sentence[200]', hoe kan ik dan nog 'sentence = strcat(sentence, keywords[random(5)]);' gebruiken? Want nu zegt ie LValue required (geheugenadres nodig ofzo?).

[ Voor 4% gewijzigd door The__Virus op 28-10-2007 20:28 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

In C99 moet main() een int returnen, net als in C++

En misschien moet je nog eens goed naar de definitie van strcat kijken. Hij retourneert namelijk geen nieuwe string, maar hij stopt de string van het tweede argument achter die van het eerste. strcat(sentence, woord) is dus voldoende om woord achter sentence te plaatsen, en het resultaat in sentence op te slaan. Wat hij retourneert is gewoon weer het eerste argument, maar daarin ben je in principe niet geïnteresseerd.

[ Voor 88% gewijzigd door .oisyn op 28-10-2007 18:11 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • The__Virus
  • Registratie: Januari 2005
  • Laatst online: 27-11 09:56
OK ook aangepast, nu werkt dat idd :). Alleen nog steeds hetzelfde probleem: er worden nog steeds waardes aangepast.

[Niet meer relevant, even verwijderd voor het geval mensen dit kopiëren]

De printf's onderin 'R', die hashtable[0][x] moeten printen, doen het alsnog niet. De eerste geeft weer twee raar tekens (of (null) ), de tweede geeft een goede zin en de derde is een Access Violation error. Heb er nu iets meer code ingezet. De case 'C' (clear) werkt dus ook niet, want al bij hashtable[0][3] gaat het fout en geeft ook deze Access Violation. Kan het zo zijn dat de keywords niet goed zijn gedefinieerd? Omdat ik ook daar geen stringlength aangeef?

edit:
De printf's geven geen error (deze 5 dan niet iig), alleen zodra de zin langer is dan een bepaalde lengte (kan ik zo niet zeggen, maar ligt op of boven de 48 chars, aangezien de derde zin zo lang is en de 4e langer en die niet correct wordt weergegeven).

edit2:
Misschien dat het probleem zich in deze regel voordoet:
sentenceaddress = (char *) malloc((strlen(sentence)+1)*sizeof(char));
Als ik namelijk stap voor stap het programma doorneemt, dan krijgt sentenceaddress iedere keer de volgende waarde:
(Yh2(Yh2

edit3:
Het heeft niet met de lengte te maken. Als ik ze allemaal dezelfde lengte geef, is het alsnog zo dat er wat mis gaat. Deze keer weer een Access Violation bij zin 4.

[ Voor 123% gewijzigd door The__Virus op 29-10-2007 15:31 ]


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 15:10

Creepy

Tactical Espionage Splatterer

En alvast voor je edit 4 :P : zou je je code kunnen beperken tot alleen het relevante stuk, of een stukje test code maken dat je probleem reproduceerd? Het is nogal een flinke lap code namelijk.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Ivo
  • Registratie: Juni 2001
  • Laatst online: 14-01 18:01

Ivo

Het zou ook erg kunnen helpen als de code die gepost wordt daadwerkelijk te compileren is. Het zou kunnen dat je ergens een buffer overflow hebt. GCC heeft pro-police op mijn machine, dus als die segfault is dat een aardige indicatie.

Edit: Hoewel het hier gaat om heapvariabelen en in hoeverre die beschermd worden weet ik niet.

[ Voor 17% gewijzigd door Ivo op 28-10-2007 23:46 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Gebruik anders een tool als Boundschecker of Valgrind.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • The__Virus
  • Registratie: Januari 2005
  • Laatst online: 27-11 09:56
Heb de code verkleind. Deze code compileert, zonder warnings, in Borland. Boundschecker of Valgrind zal ik eens naar zoeken, nog nooit van gehoord :). En wat is een segfault?

Verwijderd

Een segfault is een segmentation fault. Die kom je vooral tegen wanneer je programma geheugen probeert aan te spreken waar het niet bij mag, of wanneer je programma bijv. hardware probeert aan te spreken buiten het OS om.

Volgens mij heeft iedereen die gerommeld heeft met pointers in C weleens een segfault gehad... :P

  • The__Virus
  • Registratie: Januari 2005
  • Laatst online: 27-11 09:56
Hmm en segfaults kunnen voor Access Violations zorgen? Op zich zou die weinig moeten optreden lijkt me, alleen de groepen in de hashtabel worden gereallocced en daar zijn er op dit moment maar 100 van (HASHSIZE=100). En dan zouden de mallocs toch in de vrijgekomen ruimte hun string kunnen zetten ofzo? Lijkt me op deze schaal niet echt een probleem. Maar het probleem lijkt echt willekeurig: zodra ik ook maar van iets denk dat dat het is, dan komt na verder testen het probleem weer op een ander punt.
Het hangt niet af van het aantal items in count, maar het gebeurt wel als de count wordt veranderd (en er dus een zin in de hashtabel groep wordt gezet). Ook de zinslengte maakt niet uit, als ik zinnen van 1 woord maak, treedt het alsnog op.

Als jullie deze code compileren, krijg je dan ook access violations of rare tekens bij de laatste 5 printf's van case 'R'?

edit: de niet-ingesprongen zin was ik vergeten. Maar nu komt er telkens een access violation bij de random_sentence! Er wordt een pointer door malloc geretorneerd, maar om onbekende reden doet de rest het niet.
Dus waarom geeft dit een Access Violation?!
Het ligt ook niet aan de sentencecount, want als ik zeg 'randomaantalwoorden = random(5) + 4' dan is de sentencecount 71 en als ik zeg 'randomaantalwoorden = random(5) + 3' dan is het 91 (en dit is iedere keer hetzelfde natuurlijk, omdat random gewoon een vooraf bepaalde lijst is, niet echt random).
Als ik de (char *) weghaal (en in case 'R' op de juiste plek zet), dan doet ie het alsnog niet. Dus malloc geeft gewoon een ongeldige waarde ofzo :S.

@.oisyn: Boundschecker is voor Visual C++, niet Borland. En Valgrind is weer voor Linux en dat heb ik niet. Zijn er alternatieven?

edit: Ik denk dat ik het gevonden heb. Alles moet een \0 hebben, dus ook hashtable (HASHSIZE +1)
Ik ga het nog even testen, zal het resultaat straks melden.

edit2: OK het werkt nu idd. Bedankt allen voor jullie bijdrage! Wel lullig: door 2 bytes werkt een programma van 200MB (2,5 miljoen zinnen komen daar ongeveer op uit) niet meer :P.
Had nog wel een vraag: de free werkt op dit moment niet:

[dag dag]

Ik heb het idee dat ie alleen de pointers naar de strings weggooit, maar de strings zelf laat bestaan (aangezien er van de 90MB bij 1 miljoen zinnen slechts 4 wordt vrijgegeven). Hoe kan ik ze nou goed verwijderen? Een sterretje in free helpt iig niet.

[ Voor 91% gewijzigd door The__Virus op 31-10-2007 08:47 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 00:17
Gebruik strncpy

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • The__Virus
  • Registratie: Januari 2005
  • Laatst online: 27-11 09:56
Uuhm waar precies? En het probleem is verder al opgelost. Alleen iemand een idee voor het freeën?

  • servies
  • Registratie: December 1999
  • Laatst online: 12:06

servies

Veni Vidi Servici

The__Virus schreef op maandag 29 oktober 2007 @ 15:29:
Uuhm waar precies? En het probleem is verder al opgelost. Alleen iemand een idee voor het freeën?
Eigenlijk gewoon het omgekeerde van de malloc loop. Voor iedere malloc doe je een free, maar dan in de omgekeerde volgorde.

  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 12-11 16:48
Jammer dat je je code weer weg hebt gehaald, aangezien we daar nog aanwijzingen uit hadden kunnen halen.

Hoe je de free() op dit moment gebruikt lijkt goed. Maar dit gaat er van uit dat die strings maar 1 keer worden aangemaakt (en dat er dus niet ergens nog kopieen in het geheugen staan die niet weg worden gehaald). In principe zou er tegenover elke malloc() (of calloc()) een free() moeten staan.

Een ander punt is hoe je de count bijhoudt per regel (?). Dit doe je door een string "1" t/m "9" op te slaan in hashtable[i][0]. Zou het niet handiger zijn om in plaats daarvan een gewone integer te gebruiken? Ondanks dat hashtable[i][0] een char* is, zou je deze kunnen casten naar een integer (welke even groot is).

Het zou natuurlijk nog beter zijn als je per regel een _echte_ count integer zou gebruiken. Hiervoor zou je gebruik moeten maken van structs.

[ Voor 9% gewijzigd door VyperX op 29-10-2007 15:44 ]

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 00:17
The__Virus schreef op maandag 29 oktober 2007 @ 15:29:
Uuhm waar precies? En het probleem is verder al opgelost. Alleen iemand een idee voor het freeën?
Op de plekken waar je nu strcpy gebruikt.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • The__Virus
  • Registratie: Januari 2005
  • Laatst online: 27-11 09:56
@farlane:
Ik zie daar het voordeel niet helemaal van. Ik moet dan een maxlength aangeven en dat hoeft hier niet.
VyperX schreef op maandag 29 oktober 2007 @ 15:42:
Jammer dat je je code weer weg hebt gehaald, aangezien we daar nog aanwijzingen uit hadden kunnen halen.
Bij deze weer. Ik kom er toch weer eens niet uit :S. Als ik het zo bekijk, zou hij op z'n minst IETS moeten freeën, maar er komt totaal geen geheugen bij meer op dit moment :S.

[sorry]
Hoe je de free() op dit moment gebruikt lijkt goed. Maar dit gaat er van uit dat die strings maar 1 keer worden aangemaakt (en dat er dus niet ergens nog kopieen in het geheugen staan die niet weg worden gehaald). In principe zou er tegenover elke malloc() (of calloc()) een free() moeten staan.
Klopt inderdaad, alleen bij case 'C' moeten dus de counts niet verwijderd worden en dus alleen de strings + hun pointer in de hashgroep.
Een ander punt is hoe je de count bijhoudt per regel (?). Dit doe je door een string "1" t/m "9" op te slaan in hashtable[i][0]. Zou het niet handiger zijn om in plaats daarvan een gewone integer te gebruiken? Ondanks dat hashtable[i][0] een char* is, zou je deze kunnen casten naar een integer (welke even groot is).

Het zou natuurlijk nog beter zijn als je per regel een _echte_ count integer zou gebruiken. Hiervoor zou je gebruik moeten maken van structs.
Dank je, heb het eerder geprobeerd maar dat ging niet helemaal goed en ik kwam dit tegen dus dacht deze dirty manier maar te handhaven. Maar zo gaat het beter :).

Nu dus nog het freeën :S.
edit:
Ik heb nog eens gekeken en in 'R' zeg ik 'hashtable[hash][count+1] = randomstring;'. Dus is het logisch dat 'free(hashtable[i][x]);' gewoon zou moeten werken. Maar op dit moment werkt alleen de realloc mee volgens mij. Na deze toegevoegd te hebben wordt er een kleine 4MB vrijgegeven. Te weinig, maar toch al een begin :P. Deze zin heb ik net toegevoegd, dus wat hierboven staat is al weer beetje obsolete.

[ Voor 62% gewijzigd door The__Virus op 31-10-2007 08:46 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 00:17
The__Virus schreef op maandag 29 oktober 2007 @ 18:50:
@farlane:
Ik zie daar het voordeel niet helemaal van. Ik moet dan een maxlength aangeven en dat hoeft hier niet.
Wat meteen ook een van de meest belangrijke oorzaken is van segmentation faults en buffer overflow gaten.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • phobosdeimos
  • Registratie: Augustus 2007
  • Laatst online: 18:08
strcpy is op zichzelf verantwoordelijk voor een gigantisch aantal veiligheidslekken. En dan bedoel ik echt gigantisch veel. Zelfs strncpy is niet helemaal veilig, maar toch een pak beter dan strcpy. Strcpy is zo'n beetje als "kom maar binnen, word lekker root en maak het jezelf comfortabel" ;)

[ Voor 3% gewijzigd door phobosdeimos op 30-10-2007 09:47 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je bedoelt: C is verantwoordelijk voor een gigantisch aantal veiligheidslekken :Y)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Volgens mij bedoelen jullie: mensen zijn verantwoordelijk voor een gigantisch aantal veiligheidslekken.

Dr. Obvious to the rescue :P

[ Voor 15% gewijzigd door Confusion op 30-10-2007 11:18 ]

Wie trösten wir uns, die Mörder aller Mörder?


  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 12-11 16:48
Ik heb het programma hier nog even een keer gecompiled en er naar gekeken, maar ik kan niks aparts zien wat betreft het vrijgeven van geheugen. Ik heb ook nog zelf een kleine test gedaan met alloceren en freeen van geheugen, maar het lijkt erop dat een programma het geheugen (na freeen) nog wel 'in gebruik' houdt, totdat een ander programma het nodig heeft.

Verder zit er nog een bugje bij het clearen. Je zet daar niet de count op "0", maar veranderd de pointer. Hierdoor zou je na het clearen niet opnieuw random zinnen kunnen aanmaken. Relevante code:
C:
1
2
3
4
...
// hashtable[i][0]=(char *) 0; // <--- Foute regel
strcpy(hashtable[i][0], "0"); // <--- Verbeterde regel
...

[ Voor 7% gewijzigd door VyperX op 30-10-2007 13:07 ]

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Euh nee, zijn code is goed, de jouwe is fout. Hashtable[i] is een array van 1 char*. Hij wil die ene char* op null zetten. Wat jij doet, is de string "0" kopieren naar waar hashtable[i][0] ook maar heen wijst.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 12-11 16:48
Ik heb mijn "relevante" code aangepast in m'n vorige post...
Het ging er daar om, dat hij (in de clear) hashtable[i][0] naar een null pointer veranderde, terwijl het een string "0" moest zijn. (Analoog naar zijn initialisatie.)

Zie code van init:
C:
1
2
3
4
5
6
7
8
9
        hashtable = (char ***) malloc((HASHSIZE+1) * sizeof(char**));
        printf("-> Building dictionary index. Please wait...\n");
        for(i=0;i<HASHSIZE;i++)
        {                                                                      
                hashtable[i] = (char **) calloc(1,sizeof(char *));
                hashtable[i][0] = (char *) calloc(8,sizeof(char));
                strcpy(hashtable[i][0], "0");
        }
        printf("-> Ready!\n");

[ Voor 53% gewijzigd door VyperX op 30-10-2007 13:17 . Reden: Init code toegevoegd (ter "bewijs") :) ]

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


  • The__Virus
  • Registratie: Januari 2005
  • Laatst online: 27-11 09:56
Sorry, jij hebt nog een oude code te pakken :+. Heb het nu aangepast in mijn vorige code, dus tis mijn fout ;).

[gone]

Maar bedankt voor het meedenken. Maar jullie denken dus dat de clear wel goed is? Waarom is het dan zo dat de realloc wel geheugen 'weggeeft' (taskmgr laat met die regel een kleine 'winst' zien), terwijl de free dat niet doet? realloc naar 0 i.p.v. de free levert BTW hetzelfde op.

[ Voor 38% gewijzigd door The__Virus op 31-10-2007 08:46 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

euh, als je het zo aanpakt, dan moet je die calloc() ook niet doen, want nu lek je geheugen door een pointer te overschrijven met 0. Die overschrijving zelf kan ook wel weg, want dat doet calloc() al.

[ Voor 20% gewijzigd door .oisyn op 30-10-2007 14:38 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • VyperX
  • Registratie: Juni 2001
  • Laatst online: 12-11 16:48
The__Virus schreef op dinsdag 30 oktober 2007 @ 14:27:
Sorry, jij hebt nog een oude code te pakken :+. Heb het nu aangepast in mijn vorige code, dus tis mijn fout ;).
Aaah, vandaar. :)
Maar bedankt voor het meedenken. Maar jullie denken dus dat de clear wel goed is? Waarom is het dan zo dat de realloc wel geheugen 'weggeeft' (taskmgr laat met die regel een kleine 'winst' zien), terwijl de free dat niet doet? realloc naar 0 i.p.v. de free levert BTW hetzelfde op.
Ook al geef je het geheugen vrij, dit blijft op de heap nog wel beschikbaar voor het programma (tenzij een ander programma het gaat alloceren). En ik denk dat realloc naar 0 ondertussen gewoon free() aanroept.

Je kan het een beetje testen met het (even snel geschreven) programma hieronder:
C:
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    int x = 0;
    int i;
    
    char **strarr;
    
    if (argc > 1)
        x = atoi(argv[1]);
    else
        x = 100;
        
    
    strarr = malloc(x * sizeof(char *));
    
    for ( i = 0; i < x; i++ ) {
        strarr[i] = malloc(x);
        if (strarr[i] == NULL) {
            puts("Could not allocate memory. Aborting");
            return 1;
        }
    }
    
    printf("Allocated %d bytes. Press <Return> to empty.\n", x * x);
    i = getchar();
    
    for ( i = 0; i < x; i++ ) {
        free(strarr[i]);
    }
    fflush(stdin);
    
    printf("Freed memory. Press <Return> to fill again.\n");
    i = getchar();

    for ( i = 0; i < x; i++ ) {
        strarr[i] = malloc(x);
        if (strarr[i] == NULL) {
            puts("Could not allocate memory. Aborting");
            return 1;
        }
    }
    
    printf("Allocated %d bytes. Press <Return> to empty.\n", x * x);
    i = getchar();
    
    for ( i = 0; i < x; i++ ) {
        free(strarr[i]);
    }
    fflush(stdin);
    
    printf("Freed memory. Press <Return> to end.\n");
    i = getchar();
    
    return 0;
}


En voordat ik commentaar over dit ding krijg: dit was even snel geschreven om malloc/free interactie te testen. :)

My Dwarf Fortress ASCII Reward: ~~@~~####,.".D",.B""


  • The__Virus
  • Registratie: Januari 2005
  • Laatst online: 27-11 09:56
.oisyn schreef op dinsdag 30 oktober 2007 @ 14:38:
euh, als je het zo aanpakt, dan moet je die calloc() ook niet doen, want nu lek je geheugen door een pointer te overschrijven met 0. Die overschrijving zelf kan ook wel weg, want dat doet calloc() al.
Klopt inderdaad. Het is aangepast en het programma werkte nu 100% correct. Alleen de code die hier staat was nog steeds iets raars mee. Ik heb bij de case 'C' nu gewoon de hele hashtable verwijderd en weer opnieuw aangemaakt. Nu wordt het geheugen direct leeggemaakt.

Bedankt allemaal!
Pagina: 1