GeinMedlem sedan sep. 20005 700 inlägg ITEM *new_item(const char *name, const char *description);
MENU *new_menu(ITEM **items);
Jag vill enligt ovanstående funktionsdefinitioner skapa en godtycklig ITEM, lägga in den i en ITEM-list och sedan skapa en meny av min ITEM-list.
Jag har försökt men får bara fel. Hur skulle en enkel kod för detta se ut?
PeWMedlem sedan juni 200010 432 inlägg Det du säger med ovan funktionsprototyper är att funktionerna returnerar en adress till en ITEM och till en MENU. Vad är problemet? Att returnera en adress eller att lägga in dessa in en lista? Kom ihåg att om du ska returnera en adress så måste den adressen finnas allokerad även när funktionen terminerar, det fungerar alltså inte att skapa något på funktionsstacken och sen använda det som skapades när stacken är borta (funktionen terminerar). Endera har man med sig adressen in i funktionen och gör nåt skoj med den eller så allokerar man utrymme på heapen för detta.
GeinMedlem sedan sep. 20005 700 inlägg Nu går det visserligen att kompilera men jag får Segmentation Fault när jag försöker köra. Det tyder på fel hos någon pekare.
Felet ligger någonstans kring denna kod:
ITEM *i[1];
i[0] = new_item("Menyval1", "förklaring1");
ITEM **items = i;
MENU *m;
m = new_menu(items);
Vad gör jag för fel här?
PeWMedlem sedan juni 200010 432 inlägg ITEM **items = i;
Är helt överflödigt. Du kan lika gärna skriva 'i' direkt i anropet av new_menu. I övrigt är det inga fel just där, så jag förslår att du kollar pekarnas adresser med dbg-verktyget som du bör ha i din utvecklingsmiljö. Dvs kolla att samma adress gäller vid skapandet som efter att funktionen terminerat. En pekare är ju inget annat än en pekare och det fel som kan uppstå är om den pekar fel. Vad den pekar på är mao det intressanta.. som prototypen ser ut för new_item så skapas det något i funktionen och det som returneras är en pekare till 'detta något'. Så frågan är om 'detta något' existerar efter att funktionen terminerar. Hur allokerar du minne för 'detta något'?
GeinMedlem sedan sep. 20005 700 inlägg Jag är inte riktigt säker på om jag förstår hur du menar, här är iaf all kod:
#include <menu.h>
#include <curses.h>
#include <stdlib.h>
static void finish(int sig);
#define MY_KEY_ESCAPE 27
#define MY_KEY_SPACE 32
#define MY_KEY_ENTER1 13
#define MY_KEY_ENTER2 77
int main (void){
(void) initscr(); /* Initialize screen and the curses library */
(void) nonl(); /* tell curses not to do NL->CR/NL on output */
(void) cbreak(); /* take input chars one at a time, no wait for \n */
(void) noecho(); /* don't echo input */
ITEM *i[1];
i[0] = new_item("Menyval1", "förklaring1");
ITEM **items = i;
MENU *m = NULL;
m = new_menu(items);
post_menu(m);
refresh;
sleep(5);
unpost_menu(m);
refresh;
free_menu(m);
while (*items)
free_item (*items++);
endwin ();
exit (0);
}
static void finish(int sig)
{
endwin();
/* do your non-curses wrapup here */
exit(0);
}
PeWMedlem sedan juni 200010 432 inlägg Jag syftar på vad som finns i funktionerna new_item och new_menu. Namnet på funktionerna ger en fingervisning om att det skapas en ny item och en ny menu. Min fråga gäller hur skapas dessa item och menu. Behöver mao koden för new_item och new_menu. Om du deklarerar en Item ** så deklarerar du bara en pekare till pekare, det allokeras ju inget utrymme. Men new_item ska uppenbarligen skapa ett utrymme och om detta utrymme allokeras på funktionens interna stack kommer inte utrymmet vara giltigt när funktionen terminerar. Nu när jag ser mer av din kod så framgår att new_item ingår i menu.h som är ett lib. I det libbet allokeras en Item på heapen så problemet är något annat. (Jag antog att du petat ihop egna new_item & new_menu och ville veta hur du gjort).
Det du kan göra är att kolla adressen på resultatet från new_item. Är det NULL har allokeringen gått snett.
if((i[0]=new_item("Menyval1", "förklaring1"))==NULL)
deal_with_errors_
En annan grej som kan vara en tänkbar felorsak är 'ö'. Det är inte helt säkert att "const char *description" (som troligen är 2:a parametern i new_item) tar en unsigned char. Isf kan det balla ur med bokstäver utanför a-Z, enklast testar du det genom att skippa 'ö' och ist skriva 'o'.
I övrigt är det bättre att köra free_item uppifrån och ned istället för att som nu köra rakt fram. När en *item deletats... vad har den för adress då? Jo... 0. Nu vet jag inte vad free_item gör med pekaren, den kan ju ha en intern funktionalitet för att fixa detta. Men det kan vara värt att kolla med din bästa kompis - debuggern. Btw... borde det inte stå
while (*items)
free_item (*(items+=1));
Istället?
GeinMedlem sedan sep. 20005 700 inlägg Tack tack för alla svar! Nu förstår jag hur du menar. Jag har inte möjlighet att testa detta just nu, men såfort jag får tillfälle ska jag göra det.
GeinMedlem sedan sep. 20005 700 inlägg Det är just vid
m = new_menu(items);
som programmet krashar. Jag provade ta bort ö. Jag kollar dessutom om adressen på resultaten från new_item är NULL och det är den inte.
GeinMedlem sedan sep. 20005 700 inlägg Problemet är nu löst. Jag var tvungen att terminera listan med ett NULL-element.
PeWMedlem sedan juni 200010 432 inlägg Ja, annars får du inte villkoret i while-lopen att stämma. :)
Bra att det löste sig :bire