Willkommen ~Gast!
Registrieren || Einloggen || Hilfe/FAQ || Staff
Probleme mit der Registrierung im Forum? Melde dich unter registerEin Bild.
Autor Beitrag
000
07.03.2007, 19:26
Cpt. Rick



Hi,

ich habe ein seltsames Problem mit einem C Programm.
Es bricht an einer stelle einfach ab, ohne Error auszugeben!

Quellcode:#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <start_svr.h>
#include <unistd.h>

int startWinsock(void)
{
  WSADATA wsa;
  return WSAStartup(MAKEWORD(2,0),&wsa);
}

void menu()
{
  printf("\t._____________MENU______________.\n");
  printf("\t|                               |\n");
  printf("\t|     0   Shutdown              |\n");
  printf("\t|     1   ini laden             |\n");
  printf("\t|     2   Menu anzeigen         |\n");
  printf("\t|     3   Spiel beginnen        |\n");
  printf("\t|_______________________________|\n");
}

int main()
{  
  long rc;
  SOCKET acceptSocket_p1, acceptSocket_p2, acceptSocket_p3;
  SOCKET connectedSocket_p1, connectedSocket_p2, connectedSocket_p3;
  SOCKADDR_IN addr;
  int port1, port2, port3;
  int connect_test=0;
  int enter=1;
  int ende=1;
  char ini[40]="std.ini";
  char dir[240];
  char ini_path[280];
  int i;
  int x=1;
  char x_c[3];
  
  getcwd(dir, 240);
  
  menu();
  while(ende!=0)
  {
    printf("\n$>"); scanf("%i",&enter); // *1
    switch(enter)
    {
      case 0: //beenden
        printf("\n\tMeochten Sie den Server wirklich beenden?");
        printf("\n\tja <0>\tnein <1>\n");
        printf("\n$>"); scanf("%i",&enter);
        if(enter==0)
          ende=0;
        else
          printf("\n\t!>Vorgang Abgebrochen!");
      break;
      case 1: //ini pfad angeben
        printf("\n\tDateiname angeben: ");
        scanf("%s", &ini[40]);
        sprintf(ini_path,"%s\\%s", dir, ini);
        
        int anz=GetPrivateProfileInt("Antrieb_Kit", "anz", 0, ini_path);
        
        int x_antrieb_kit[anz+1];
        int y_antrieb_kit[anz+1];
        int z_antrieb_kit[anz+1];
        
        for(i=1;i<=anz;i++)
        {
          sprintf(x_c,"%d",x); x_antrieb_kit[i]=GetPrivateProfileInt("Antrieb_Kit", x_c, 0, ini_path);  x++;
          sprintf(x_c,"%d",x); y_antrieb_kit[i]=GetPrivateProfileInt("Antrieb_Kit", x_c, 0, ini_path);  x++;
          sprintf(x_c,"%d",x); z_antrieb_kit[i]=GetPrivateProfileInt("Antrieb_Kit", x_c, 0, ini_path);  x++;        
        }    
        
        printf("%i,%i,%i",x_antrieb_kit[1],y_antrieb_kit[1],z_antrieb_kit[1]);
        
      break;
      case 2: //Menu anzeigen
        menu();
      break;    
      case 3: //Spiel starten
        connect_test=start_svr();
        if(connect_test!=13)
        {
          printf("!>Der Server konnte nicht gestartet werden!\n");
          closesocket(acceptSocket_p1);
          closesocket(acceptSocket_p2);
          closesocket(acceptSocket_p3);
          closesocket(connectedSocket_p1);
          closesocket(connectedSocket_p2);
          closesocket(connectedSocket_p3);
          WSACleanup();
          system("PAUSE");
          connect_test=0;
        }
        else
        {
          //Game Operations
        }  
      break;
      default:
        printf("\n!>Ungeultige Eingabe!\n");
      break;
    }
  }    
  
  if(connect_test==13) //Wenn der server gestartet wurde werden nun die Socktes gelöscht
  {
    closesocket(acceptSocket_p1);
    closesocket(acceptSocket_p2);
    closesocket(acceptSocket_p3);
    closesocket(connectedSocket_p1);
    closesocket(connectedSocket_p2);
    closesocket(connectedSocket_p3);
    WSACleanup();
  }
  return 0;
}
Nachdem ich "1" und den Namen der ini eingegeben habe liest er diese auch aus, geht dann aus der switch() und bricht dann an der Stelle *1 ab.

Ich bin mit meinem Latein am Ende, ich sehe weder einen logischen Fehler, noch bekomme ich einen Error im Compiler!

--

zum Seitenanfang zum Seitenende Profil || Suche
001
07.03.2007, 19:56
feigling



Was soll denn das da sein:

scanf("%s", &ini[40]);

Benutze scanf("%s", ini); bzw am Besten fgets(ini, 40, stdin);

Edit: Und bist du sicher, es soll

Quellcode:
#include <start_svr.h>

sein und nicht

Quellcode:
#include "start_svr.h"
?

--


Dieser Beitrag wurde am 07.03.2007 um 20:00 von feigling bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
002
07.03.2007, 20:06
Cpt. Rick



fgets(ini, 40, stdin);

funktioniert ganricht, da bricht er das Programm schon bei der Eingabe des Namens der ini ab!

scanf("%s", ini);
Führt zum selben Fehler wie mit: scanf("%s", &ini[40]);

Das Programm bricht an der Stelle *1 ab!

EDIT: #inculde "start_svr.h" ändert auch nichts am Abbruch.
Aber da es eine eigene header datei ist, muss das "" rein, thx, hatte ich übersehen!

--


Dieser Beitrag wurde am 07.03.2007 um 20:10 von Cpt. Rick bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
003
07.03.2007, 20:22
feigling



Was heißt, fgets(ini, 40, stdin); funktioniert garnicht ...

Natürlich funktioniert das.

Quellcode:
int
main(void)
{
    char ini[40];

    fgets(ini, 40, stdin);
    printf("%s", ini);

    return 0;
}

Quellcode:
12345 67890
12345 67890

und das funktioniert sogar besser als scanf, da scanf bei Leerzeichen abbricht, wenn man das nicht im fomat String von scanf anders behandelt. Das einzige, was du bei fgets noch machen musst, ist das newline Zeichen am Ende zu löschen.

sprintf(ini_path,"%s\\%s", dir, ini); bringt dir auch genau 0, weil dir undefniert ist, da du dir nirgendwo einen Wert zuweist.

--


Dieser Beitrag wurde am 07.03.2007 um 20:22 von feigling bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
004
07.03.2007, 20:44
Cpt. Rick



Hmm...also das Programm läuft trotz dieser Fehler bis zu der Stelle der Eingabe VOR dem switch!!!

Das auslesen der ini ist kein Problem. In einem Test habe ich mir die Werte zurückgeben lassen, das Programm bricht erst an der Stelle die im Code mit // *1 markiert ist ab!

Edit: Hier: getcwd(dir, 240); erhällt dir seinen Wert!

--


Dieser Beitrag wurde am 07.03.2007 um 20:56 von Cpt. Rick bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
005
07.03.2007, 21:23
Cpt. Rick



http://treky21.tr.funpic.de/server.exe

Das ist das kompilierte Programm.
Die ini sieht folgendermaßen aus:
Quellcode:[Antrieb_Kit]
anz=3
1=46
2=46
3=46

4=2
5=2
6=2

7=24
8=69
9=99
Der Abbruch taucht auf wenn man "1" eingibt um die ini einzulesen und dann verlässt das Programm die siwtch Anweisung und sollte "$> " anzeigen um eine Eingabe zu ermöglichen, doch hier bricht das Programm ab (Die ini wird jedoch ausgelsen!!!) !

--


Dieser Beitrag wurde am 07.03.2007 um 21:23 von Cpt. Rick bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
006
07.03.2007, 23:00
HammerBlade



Hast du mal dazu einen Debugger deiner Wahl befragt, z.B. GDB?

--

"Mit C++ (noch besser mit C) kann man sich _sehr_ leicht in den Fuss schiessen." - theDon
Auspack und freu! - Auszug aus einer, aus dem japanischen übersetzten, Bedienugsanleitung für ein Spielzeugaquarium.
--
Photon Audio Player | Majestic42.net | How To Ask Questions The Smart Way

zum Seitenanfang zum Seitenende Profil || Suche
007
07.03.2007, 23:41
feigling



Ah, das getcwd(dir, 240); hab ich ned gesehen. Dann scheint es irgendwo wohl nen Bufferüberlauf zu geben oder so, von daher siehe Post von HammerBlade.

--

zum Seitenanfang zum Seitenende Profil || Suche
008
11.03.2007, 12:42
Cpt. Rick



GDB ist leider Linux, da ich aber auf Win programmiere nützt mir das also nicht viel.
Ich hab aber einen Debugger in Dev Cpp gefunden.

Ich bekomme nun beim Kompilieren folgenden error:

Quellcode:Line 66: unreadable code at beginning of switch statement Die besagte Stelle:

Quellcode:65: printf("\n$>"); scanf("%i", &enter);
66: switch(enter)
Der Debugger gibt folgende Fehlermeldung zurück:

An Access Violation (Segmentation Fault) raised in your program.

Nach dem der Error Nachricht zeigt der Marker auch auf Zeile 65.
Wenn ich jetzt noch wüßte was ich damit anfangen soll O.O

--


Dieser Beitrag wurde am 11.03.2007 um 12:44 von Cpt. Rick bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
009
11.03.2007, 13:49
HammerBlade



Welchen Compiler/IDE verwendest du denn sonst?

GDB gibts sehr wohl für Windows ( http://mesh.dl.sourceforge.net/sourceforge/mingw/gdb-6.3-2.exe ) und du hast ihn vielleicht sogar benutzt, wenn du DevC++ mit MinGW benutzt hast.

Dein Problem ist etwas komisch, weil der GCC sich erst mit dem -g Flag (Symbols-Flag) darüber auslässt. Das Problem findet man auch bei goto's und das switch ist eine Art verkapptes goto.

Quellcode:.   switch(enter)
    {
      case 0: //beenden
        printf("\n\tMeochten Sie den Server wirklich beenden?");
        printf("\n\tja <0>\tnein <1>\n");
        printf("\n$>"); scanf("%i",&enter);
        if(enter==0)
          ende=0;
        else
          printf("\n\t!>Vorgang Abgebrochen!");
      break;
      case 1: //ini pfad angeben
      { // <---- Die Klammer hier...
        printf("\n\tDateiname angeben: ");
        scanf("%s", &ini[40]);
        sprintf(ini_path,"%s\\%s", dir, ini);
        
        int anz=GetPrivateProfileInt("Antrieb_Kit", "anz", 0, ini_path);
        
        int x_antrieb_kit[anz+1];
        int y_antrieb_kit[anz+1];
        int z_antrieb_kit[anz+1];
        
        for(i=1;i<=anz;i++)
        {
          sprintf(x_c,"%d",x); x_antrieb_kit[i]=GetPrivateProfileInt("Antrieb_Kit", x_c, 0, ini_path);  x++;
          sprintf(x_c,"%d",x); y_antrieb_kit[i]=GetPrivateProfileInt("Antrieb_Kit", x_c, 0, ini_path);  x++;
          sprintf(x_c,"%d",x); z_antrieb_kit[i]=GetPrivateProfileInt("Antrieb_Kit", x_c, 0, ini_path);  x++;        
        }    
        
        printf("%i,%i,%i",x_antrieb_kit[1],y_antrieb_kit[1],z_antrieb_kit[1]);
      } // <---- ...und die Klammer hier fehlten!
      break;
Du deklarierst im case-1-Block Variablen. Diese Deklaration ist auch im case-2-Block noch gültig, wird aber durch einen direkten Ansprung von case-2 durch das switch übersprungen, so dass die Variablen nicht deklariert wurden, sie aber gültig sind. Das führt zu deinem Fehler.

Daher musst du dafür sorgen, dass die Variablen aus case-1 auch nur in case-1 gültig sind. Du musst also ihr Scope verkleinern, indem du die oben angezeigen Klammern setzt.

Edit:
Vorsicht. Du machst da Sachen, die nur mit GCC zu funktionieren scheinen:

Quellcode:.       int x_antrieb_kit[anz+1];
        int y_antrieb_kit[anz+1];
        int z_antrieb_kit[anz+1];
Das funktioniert z.B. mit VisualC so nicht. Das scheint eine GCC-Extension zu sein.

So wäre es "richtiger/normaler":

Quellcode:.       int* x_antrieb_kit = (int*)malloc((anz+1) * sizeof(int));
        int* y_antrieb_kit = (int*)malloc((anz+1) * sizeof(int));
        int* z_antrieb_kit = (int*)malloc((anz+1) * sizeof(int));
        
        for(i=1;i<=anz;i++)
        {
          [...]      
        }    
        
        printf("%i,%i,%i",x_antrieb_kit[1],y_antrieb_kit[1],z_antrieb_kit[1]);
        
        free(x_antrieb_kit);
        free(y_antrieb_kit);
        free(z_antrieb_kit);

--

"Mit C++ (noch besser mit C) kann man sich _sehr_ leicht in den Fuss schiessen." - theDon
Auspack und freu! - Auszug aus einer, aus dem japanischen übersetzten, Bedienugsanleitung für ein Spielzeugaquarium.
--
Photon Audio Player | Majestic42.net | How To Ask Questions The Smart Way


Dieser Beitrag wurde am 11.03.2007 um 14:52 von HammerBlade bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
010
11.03.2007, 17:48
theDon



Variable-Length-Arrays sind Teil von C99, das ist keine GCC-Extension.

--

\o tanz den naziprau! o/

And more than ever, I hope to never fall,
Where enough is not the same it was before

zum Seitenanfang zum Seitenende Profil || Suche
011
11.03.2007, 18:11
feigling



Außerdem castet man malloc in c nicht.

--

zum Seitenanfang zum Seitenende Profil || Suche
012
11.03.2007, 22:52
Cpt. Rick



Mit den Klammern ({ & }) funktioniert es wieder einwandfrei!

Danke Jungs, ihr sied die Besten! ;)

--

zum Seitenanfang zum Seitenende Profil || Suche
013
12.03.2007, 00:13
Master Pegasus



Man castet malloc nicht? In C++ verwendet man doch new und delete und zumindest mir wurde an der Uni im C-Praktikum schon beigebracht malloc zu casten.

--

Was immer auch geschieht: Nie sollt Ihr so tief sinken, von dem Kakao, durch den man Euch zieht, auch noch zu trinken! -- Erich Kästner

zum Seitenanfang zum Seitenende Profil || Suche
014
12.03.2007, 02:05
HammerBlade



Zitat:
theDon postete
Variable-Length-Arrays sind Teil von C99, das ist keine GCC-Extension.
Okay VisualC war ein hinkender Vergleichs-Compiler, bei dem ich im Nachhinein nicht mal herausgefunden habe, ob oder wie man da verschiedene Standards ala -std=c99/... vorgeben kann.

Zitat:
feigling postete
Außerdem castet man malloc in c nicht.
Ich muss zu meiner Verteidigung sagen, dass ich mich nie wirklich speziell mit C alleine beschäftigt habe. Ich verwende im Allgemeinen C++.

Man castet anscheinent malloc in C deswegen nicht, weil man es nicht muss, in C++ muss man es sehr wohl casten, daher war mir nicht bewusst, dass man es in C nicht braucht.

Man lernt nie aus.

--

"Mit C++ (noch besser mit C) kann man sich _sehr_ leicht in den Fuss schiessen." - theDon
Auspack und freu! - Auszug aus einer, aus dem japanischen übersetzten, Bedienugsanleitung für ein Spielzeugaquarium.
--
Photon Audio Player | Majestic42.net | How To Ask Questions The Smart Way


Dieser Beitrag wurde am 12.03.2007 um 02:08 von HammerBlade bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
015
12.03.2007, 16:28
TheTinySteini



In C++ benutzt man ja auch kein malloc...

--

TheTinySteini
Coder Poke646
"Don't Panic" - Hitchhiker's Guide to the Galaxy

zum Seitenanfang zum Seitenende Profil || Suche
016
12.03.2007, 17:48
Kriz



Zitat:
Aus http://www.pronix.de/pronix-753.html
Das Typencasting der Funktion malloc() ist in C nicht notwendig und kann auch weggelassen werden. ANSI C++ schreibt allerdings ein Casten des Typs void * vor. Zwar halten Sie hier ein C-Buch in den Händen, aber häufig ist der Compiler auf C++-Projekten eingestellt. ...

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
017
12.03.2007, 18:22
feigling



Man castet malloc() in C nicht, weil es folgenden Grund hat:

Vergisst man mal stdlib.h zu includen, denkt sich der Compiler, dass malloc int zurückgibt, was natürlich falsch ist, da diese Funktion nen void Pointer zurückgibt. Castet man nun, denkt sich der Compiler .. "ok, da der Programmierer castet, scheint das alles zu stimmen" und es kommt totaler Müll bei raus. Castet man nicht, bekommt man vom Compiler solch eine Warnung "warning: assignment of pointer from integer lacks a cast" -> man sieht, dass da irgendwas mit malloc nicht stimmt. Daher sollte man in C malloc, realloc, calloc .. nicht casten.

--


Dieser Beitrag wurde am 12.03.2007 um 18:23 von feigling bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
018
12.03.2007, 19:35
oxff



eigtl. ist es egal, ob der Compiler annimt, dass es jetzt einen int zurückgibt anstatt eines void *. Beide Typen sind als `native breite' definiert, also meistens 32bit. Intern ist jeder Pointer ohnehin ein int. Einzig die calling convention könnte hier also einen Strich durch die Rechnung machen; da kommt es dann auf die default Calling-Convention deines Compilers und deiner libc an.

--

mwcollect - mein Projekt | oxlog - mein blog | happyhardcore.com Stream - gute Musik

zum Seitenanfang zum Seitenende Profil || Suche
019
12.03.2007, 21:30
hausi



Das mit der nativen Breite von ints stimmt ja bisher schon, allerdings gibts da jetzt ja leider auch eine Ausnahme:

Zitat:
man gcc schrieb
-m64
Generate code for a 32-bit or 64-bit environment. The 32-bit environment sets int, long and pointer to 32 bits and generates code that runs on any i386 system. The 64-bit environment sets int to 32 bits and long and pointer to 64 bits and generates code for AMD's x86-64 architecture.

--


Dieser Beitrag wurde am 12.03.2007 um 21:33 von hausi bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
020
12.03.2007, 21:32
hausi



Sorry, doppelpost...

--


Dieser Beitrag wurde am 12.03.2007 um 21:33 von hausi bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
021
12.03.2007, 23:38
theDon



Zitat:
0xFF postete
eigtl. ist es egal, ob der Compiler annimt, dass es jetzt einen int zurückgibt anstatt eines void *. Beide Typen sind als `native breite' definiert, also meistens 32bit. Intern ist jeder Pointer ohnehin ein int.
Schwachsinn: ``A pointer may be converted to an integral type large enough to hold it; the required size is implementation-dependent.'' --TCPL, A6.6

--

\o tanz den naziprau! o/

And more than ever, I hope to never fall,
Where enough is not the same it was before

zum Seitenanfang zum Seitenende Profil || Suche
022
12.03.2007, 23:47
Kriz



Damit dürften wir jetzt wohl jeden Aspekt durchgekaut haben und kommen zu dem Schluß, der bereits vor Äonen festgestellt worden ist: malloc() wird nicht gecastet, sofern der Compiler gerade auf C ist.

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche
023
19.03.2007, 17:45
default



c compiler die älter als ansi sind returnen für malloc char * anstelle von void *, daher musste man da explizit casten, man gewinnt durch den cast also rückwärtskompatibilität von ca 20y.

--

Du musst Deine Bandbreite verbreitern, damit du breiter wirst von der Bandbreite her und ein breiteres Publikum ansprechen kannst.

zum Seitenanfang zum Seitenende Profil || Suche
024
19.03.2007, 19:24
Kriz



Hm, ob man da nicht noch mit far und near rumpopeln müsste?

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)

zum Seitenanfang zum Seitenende Profil || Suche