Avatar billede hyperguy Nybegynder
15. maj 2004 - 16:37 Der er 24 kommentarer og
1 løsning

Segmentation fault.

Jeg har lavet lidt ud fra den artikel fra arne_v og det virker også fint. Men ligeså snart jeg laver cin >> input; så kommer den med Segmentation fault når jeg trykker enter.

Nogen der kan se min fejl ?

#include "mysql.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int main()
{
    MYSQL *handle;
    char sqlcmd[200], input;
    int i;
    handle= mysql_init(NULL);
    if(handle == NULL)
    {
        printf("MySQL error: %s", mysql_error(handle));
        exit(1);
    }
    if(!mysql_real_connect(handle, "localhost", "tabernar_dk", "hyper", "tabernar_dk", 0, NULL, 0))
    {
        printf("MySQL error: %s", mysql_error(handle));
        exit(1);
    }
    cin >> input;
    for(i=0; i<10; i++)
    {
        sprintf(sqlcmd, "INSERT INTO testc VALUES (%d,'%s')", i, input);
        mysql_query(handle, sqlcmd);
    }
    mysql_close(handle);
    return 0;
}
Avatar billede strych9 Praktikant
15. maj 2004 - 17:08 #1
prøv at debugge med gdb.

gdb dit-program-navn
run

den segfaulter

skriv bt for at få et backtrace. Det er muligt at du skal compile det med -g switch til gcc for at få debug symbols med.
Avatar billede hyperguy Nybegynder
15. maj 2004 - 17:17 #2
Ok den skrev noget til mig nu, men jeg ved ikke hvad det betyder.

(gdb) run
Starting program: /home/hyper/c++/sql
Input: hej

Program received signal SIGSEGV, Segmentation fault.
0x400dcf7e in vfprintf () from /lib/libc.so.6
(gdb) bt
#0  0x400dcf7e in vfprintf () from /lib/libc.so.6
#1  0x400f40c3 in vsprintf () from /lib/libc.so.6
#2  0x400e440d in sprintf () from /lib/libc.so.6
#3  0x080496a1 in main () at sql.c:25


Det fik jeg ud.
Avatar billede strych9 Praktikant
15. maj 2004 - 17:20 #3
Så fejlen den crasher på ligger i linje 25, og hvis dit cut/paste er korrekt så er det mysql_query(handle, sqlcmd);
Avatar billede strych9 Praktikant
15. maj 2004 - 17:21 #4
men tror du ikke at det er fordi du forsøger at behandle en string som en int?
Jeg er ikke den store C/C++ haj, men umiddelbart ser det sådan ud.
Avatar billede hyperguy Nybegynder
15. maj 2004 - 17:23 #5
Det havde jeg også tænkt på.

Men da jeg havde cut/paste det fra arne_v´s artikel gik jeg alligevel ud fra den var god nok.

Kan det være fordi sqlcmd er tom?

Men det burde den ikke være med "sprintf(sqlcmd, "INSERT INTO testc VALUES (%d,'%s')", i, input);"
Avatar billede strych9 Praktikant
15. maj 2004 - 17:41 #6
måske kan du teste sqlcmd med en if om den er NULL ligesom der gøres i if(handle == NULL)?

Så vidt jeg ved segfaulter programmer normalt når du kommer ud for en eller anden situation som de ikke forstår at håndtere primært pga manglende fejl håndtering. Så det kan være alt muligt. Sidst jeg var ude for noget der lignede det her lidt var pga en firewall som lukkede mysql porten lokalt og programmet ikke vidste hvad det skulle gøre så. Men det bliver der vist testet for i ovenstående kode så det er nok ikke det. Men alligevel test den der om indholdet er NULL :)
Du kan også sætte breakpoints med gdb og aflæse hvad variabel indhold er osv. Det er et ret kraftfuldt værktøj, men vi skal vist have arne til at skrive en artikel om det :)
Avatar billede hyperguy Nybegynder
15. maj 2004 - 17:49 #7
Jeg har fået det til at virke nu. Jeg lavede det til en pointer så virkede det.
Avatar billede strych9 Praktikant
15. maj 2004 - 18:02 #8
cool

så lad os eventuelt dele pointene :)
Avatar billede hyperguy Nybegynder
15. maj 2004 - 18:03 #9
Hehe du får bare det hele.. har nok af det:)
Avatar billede arne_v Ekspert
16. maj 2004 - 00:23 #10
segmentation fault = forsøg på at bruge memory på en ikke eksisterende adresse

    char sqlcmd[200], input;

input erklæres til char

    cin >> input;

et bogstav læses ind i input f.eks. 'A'

        sprintf(sqlcmd, "INSERT INTO testc VALUES (%d,'%s')", i, input);

%s forventer et argument med adressen på starten af et char array

det faktisk argument er 'A' = 65

den forsøger derfor at læse et char array som starter i adresse 65

det er ikke en valid adresse => segmentation fault
Avatar billede bertelbrander Novice
16. maj 2004 - 00:54 #11
Er løsningen så at lave %s om til en %c eller at lave input om til et array?

Løsningen er vel ikke at lave input om til en pointer?
Avatar billede arne_v Ekspert
16. maj 2004 - 00:58 #12
De to mest oplagte muligheder er:

char input;
%c

og:

char input[100];
%s

Jeg ved ikke engang hvad:

char *input;
cin >> input;

gør.
Avatar billede bertelbrander Novice
16. maj 2004 - 01:00 #13
Jeg vil tro det giver segfault, eller anden ubehagelig opførsel?

Jeg troede du havde lavet koden?
Avatar billede arne_v Ekspert
16. maj 2004 - 01:02 #14
Min kode ser sådan her ud:

    for(i=0; i<10; i++)
    {
        sprintf(sqlcmd, "INSERT INTO t1 VALUES (%d,'%s')", i, "Dette er en test");
        mysql_query(handle, sqlcmd);
    }
Avatar billede hyperguy Nybegynder
16. maj 2004 - 13:10 #15
Nu er jeg så lige kommet ind i et nyt problem.
Når jeg har den cin >> input, så hvis jeg skriver mere end 1 ord, looper den min sql query og skriver ikke det hele ind i en post, men hvert ord i hver post, ind i sqlen.
Hvordan kan jeg lave sådan at en variabel kan have en sætning?
Avatar billede arne_v Ekspert
16. maj 2004 - 13:12 #16
cin.getline(input,sizeof(input));
Avatar billede hyperguy Nybegynder
16. maj 2004 - 14:33 #17
Det virker sådan nogenlunde, problemet er at jeg har det til at stå i en while loop, så den skulle gerne stoppe og be om brugerens input. Jeg har det stående i en function som jeg kalder og en anden function der bliver galt bagefter. Men den sidste function bliver kaldt med det samme.
Avatar billede arne_v Ekspert
16. maj 2004 - 21:16 #18
Det forstod jeg ikke noget af.
Avatar billede hyperguy Nybegynder
16. maj 2004 - 21:22 #19
Jeg har en function der hedder menu_1(); og en der hedder mainMenu();
I min menu_1(); har jeg mit input crap som ikke virker helt.
I min mainMenu(); har jeg min hoved menu i programmet.

jeg har så lavet en whileloop der kører så længe "quit" ikke bliver valgt.

Det sådan sådan her:

menu_1();
mainMenu();
break;

Mit problem er at når jeg bruger cin.getline(input,sizeof(input)); går den helt ned til break med det samme, men bruger jeg cin >> input stopper den i menu_1() og venter TIL jeg har skrevet noget input.
Avatar billede arne_v Ekspert
16. maj 2004 - 21:27 #20
Det lyder som at du bruger både
  cin >>
og
  cin.getline
i koden og at det giver en anden opførsel end det du forventer (hvilket ofte er
set).
Avatar billede hyperguy Nybegynder
16. maj 2004 - 21:28 #21
Ja, når jeg skal vælge menu (et tal) bruger jeg cin, men ved til at smide noget i min variabel input, bruger jeg det du skrev. Men den opføre sig ikke på samme måde, så jeg ved ikke helt hvordan jeg skal lave det. Min kode er blevet lidt for lang til at cut/paste herinde desværre.
Avatar billede arne_v Ekspert
16. maj 2004 - 21:36 #22
Så lav en kopi af din kode og slet det der er overflødigt for at illustrere
problemet i kopien og post den.
Avatar billede hyperguy Nybegynder
16. maj 2004 - 21:42 #23
int mainMenu()   
{
    int menuValg;
    clear();
    cout << "|-----Menu-----|\n1) Skriv til database\n2) Laes fra database\n";
    cout << "Menu valg: ";
    cin >> menuValg;
    return menuValg;
}

void menu_1()
{
        /* Mysql crap ting før det her */
    cout << "|-----Skriv til Database-----|\n\n";
    cout << "Input: ";
    getline(cin, input,sizeof(input));
    sprintf(sqlcmd, "INSERT INTO testc (text) VALUES ('%s')", input);
    mysql_query(handle, sqlcmd);
    mysql_close(handle);
}


int main()
{
    int menuValg;
    menuValg = mainMenu();
    do
    {
        switch (menuValg)
        {
        case 1:
            menu_1();
            mainMenu();
            break;
        default:
            menuValg = mainMenu();
        }
       
    }
    while (menuValg != 9);
    return 0;
}

Det virker fint med menuvalg. Mit problem er somsagt at med "cin >> input;" stopper den mellem menu_1(); og mainMenu(); for at vente på jeg skriver noget. Men med "cin.getline(input,sizeof(input));" hopper den bare videre ned til mainMenu(); i stedet for at stoppe og vente på jeg skriver noget ind til den.
Avatar billede arne_v Ekspert
16. maj 2004 - 22:08 #24
Prøv og kig på denne kode:

#include <iostream>
#include <cstdlib>

using namespace std;

int menu_main() 
{
    cout << "|-----Menu-----|" << endl;
    cout << "1) Skriv til database" << endl;
    cout << "2) Laes fra database" << endl;
    cout << "9) Afslut" << endl;
    cout << "Menu valg: ";
    //virker ikke:
    //int menuValg;
    //cin >> menuValg;
    //return menuValg;
    // virker:
    char input[100];
    cin.getline(input, sizeof(input));
    return atoi(input);
}

void menu_1()
{
    cout << "|-----Skriv til Database-----|" << endl;
    cout << endl;
    cout << "Input: ";
    char input[100];
    cin.getline(input, sizeof(input));
    cout << "Skriver '" << input << "' til databasen ..." << endl;
}


int main()
{
    bool more = true;
    while(more)
    {
        int menuValg = menu_main();
        switch (menuValg)
        {
            case 1:
                menu_1();
                break;
            case 9:
                more = false;
                break;
            default:
                // nothing
                break;
        }
    }
    return 0;
}

specielt "virker ikke" og "virker"

PS: Der er også andre løsninger, men jeg kan lide denne her
Avatar billede hyperguy Nybegynder
16. maj 2004 - 22:32 #25
Nice det virker perfekt.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester