getenv() will nicht so recht
-
Schönen guten Tag!
Bin hier grad seit Stunden am rumölen, und krigs einfach nicht in griff. Der Sourcecode ist aus dem GenICam SDK und sollte Theoretisch sofort funktionieren. Theoretisch. Es geht schon damit los, dass er sich beim beschaffen der umgebungsvariablen wegschießt. GENICAM_ROOT existiert laut set inner console ...Bitte steinigt mich nicht, ich bin in C++ ein absoluter neuling
Programmcode:
#define _WIN32_WINNT 0x0502 #include <Windows.h> #include <stdio.h> #include <conio.h> #include <string> // Required for using GenApi #include "GenApi/GenApi.h" using namespace GenICam; using namespace GenApi; int setenv( const char name[], const char value[], int replace ) { GC_UNUSED( replace ); ::SetEnvironmentVariable( name, value ); return 0; } int main(int /*argc*/, char* /*argv[]*/) { // Setup the environment variables pointing out GenICam's home directory // The following code assumes that an environment variable GENICAM_ROOT exists // Note that this variable is normally not present at runtime std::cout << getenv("GENICAM_ROOT") << std::endl; ...
Den fehler bekomme ich beim compilieren, ohne die "getenv..." zeile läuft das ganze durch.
Fehlerausgabe:
Eine Ausnahme (erste Chance) bei 0x1023b130 (msvcr80d.dll) in UsingGenApi_1_MDd_VC80_v_.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000.
der debugger jagt mich dann in die strlen.asm mit der eben erwähnten fehlermeldung.
strlen.asm
... main_loop: mov eax,dword ptr [ecx] ; read 4 bytes <--- stoppt der debugger mov edx,7efefeffh add edx,eax xor eax,-1 ...
Was mach ich falsch?
-
Ich weis nicht ob dir die Antwort hilft, aber du versuchst irgendwo auf den Speicher zuzugreifen, wo du keine Leserechte hast.
-
getenv darf wohl einen NULL Zeiger zurückgeben, wenn die Environment Variable nicht gesetzt ist!
Und dann... krachts!
-
blacksheep1 schrieb:
Bin hier grad seit Stunden am rumölen, und krigs einfach nicht in griff.
Was mach ich falsch?Vielleicht eine andere Sorte Öl verwenden? Maiskeimöl? Oder darfs der Kürbiskernöl sein?
Spaß beiseite:
Da Du ja geschrieben hast, daß Du absolute C++ Neuling bist: zunächst ich empfehle Dir die Funktion getenv() erstmal ohne die namespaces GenICam und genApi zu verwenden. Also Konzentration aufs wesentliche, denn getenv() hat damit nix zu tun.Desweiteren lese ich in Deinem Code sowohl getenv() als auch setenv(). ist das beabsichtigt?
Wie äußert sich denn das "er sich beim beschaffen der umgebungsvariablen wegschießt"? Fehlermeldung am Bildschirm?
Ich würde blind darauf tippen, daß Du für die Strings keinen (oder zu kleinen) Speicher reserviert hast.
Martin
-
wenn ich jetzt vor die zeile einfach nochmal per hand diese Variable setze, sollte er doch keinen NULL-Zeiger zurückgeben können, oder?! Der fehler ist aber unverändert...
... setenv("GENICAM_ROOT", "C:\\GenICamSDK", false); std::cout << getenv("GENICAM_ROOT") << std::endl; ...
@Mmacher:
Hier mal die komplette cpp-Datei. Dazu gabs nen riesigen haufen headerfiles und nen paar lib's/dll's. Ich nehme mal an, dass die Umgebungsvariablen in den restlichen programmteilen noch gebraucht werden.// Required for SetDllDirectory; this function exists only with WinXK SP1 or higher #define _WIN32_WINNT 0x0502 #include <Windows.h> #include <stdio.h> #include <conio.h> #include <string> // Required for using GenApi #include "GenApi/GenApi.h" using namespace GenICam; using namespace GenApi; int setenv( const char name[], const char value[], int replace ) { GC_UNUSED( replace ); ::SetEnvironmentVariable( name, value ); return 0; } int main(int /*argc*/, char* /*argv[]*/) { // Setup the environment variables pointing out GenICam's home directory // The following code assumes that an environment variable GENICAM_ROOT exists // Note that this variable is normally not present at runtime std::string MyGenICamRoot( getenv("GENICAM_ROOT") ); // GENICAM_ROOT_VERSION holds the path to the GenICam root directory // GENICAM_ROOT_VERSION expands to something like "GENICAM_ROOT_V1_0" depending on the GenICam version used // This variable must be present at runtime setenv(GENICAM_ROOT_VERSION, MyGenICamRoot.c_str(), false ); // GENICAM_CACHE holds a path to a location were cached XML files are stored // This location must be writable therefore it is normally different from the home directory // were users without admin rights cannot write files. std::string MyGenICamBCache( MyGenICamRoot ); MyGenICamBCache += "/xml/GenApi/cache"; setenv("GENICAM_CACHE", MyGenICamBCache.c_str(), false ); // The GenICam DLLs from the installation must be in the PATH. // Note that SetDllDirectory is avaliable only under WinXP SP1 and higher std::string MyGenICamBin( MyGenICamRoot ); MyGenICamBin += "/bin/Win32_i86"; ::SetDllDirectory( MyGenICamBin.c_str() ); // Get a camera description file // This is an example for a very primitive camera description file const GenICam::gcstring CameraDescriptionFile = "<?xml version=\"1.0\" encoding=\"utf-8\"?> \n" "<RegisterDescription \n" " ModelName=\"UsingGenApiExample\" \n" " VendorName=\"Generic\" \n" " ToolTip=\"Sample nodes\" \n" " StandardNameSpace=\"GEV\" \n" " SchemaMajorVersion=\"1\" \n" " SchemaMinorVersion=\"0\" \n" " SchemaSubMinorVersion=\"1\" \n" " MajorVersion=\"2\" \n" " MinorVersion=\"3\" \n" " SubMinorVersion=\"4\" \n" " ProductGuid=\"55D10620-B3F2-428f-AA26-E613FDACB0F2\" \n" " VersionGuid=\"5B673AA5-1C47-417e-959D-CB5445368A5A\" \n" " xmlns=\"http://www.genicam.org/GenApi/Version_1_0\" \n" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" " xsi:schemaLocation=\"http://www.genicam.org/GenApi/Version_1_0 \n" " http://www.genicam.org/GenApi/GenApiSchema_Version_1_0.xsd\"> \n" " \n" " <Integer Name=\"TheValue\"> \n" " <Value>0</Value> \n" " </Integer> \n" " \n" "</RegisterDescription> \n"; // Create a camera access object and load the camera description file CNodeMapRef Camera; Camera._LoadXMLFromString(CameraDescriptionFile); // Get the Value node and access it CIntegerPtr ptrValue = Camera._GetNode("TheValue"); // access the node assert( 0 == *ptrValue()); *ptrValue = 42; int64_t Value = *ptrValue(); assert( 42 == Value); printf("UsingGenApi_1 : GenICam worked all right.\n"); return ! (42 == Value); }
Das "wegschießen" (sry :D) äußert sich durch die oben gepostete nachricht inner ausgabe vom Debugger und durch eine Meldungsbox die aufpoppt und mir anbietet zu unterbrechen oder weiterzumachen. Bei zweitem wiederholt sich die meldung beliebig oft.
PS: Geiles forum, hier kommt man ja garnicht mitm antwortet hinterher
-
Der Gedanke ist schon nicht schlecht.
Aber woher weißt Du daß setenv() erfolgreich war?Deshalb: Den Rückgabewert von setenv() auswerten, ob es erfolgreich war!
Beispiel für Ursache: Eingeschränkte User-RechteMartin
-
Oje, Da Du Deinen letzten Beitrag komplett neu editiert hast, paßt meine letzte Antwort natürlich nicht mehr dazu.
Bitte nutze deshalb die Editierfunktion hier im Forum nur für kleinere Korrekturen, sonst kann der rote Faden für uns (und auch für andere Leser!) total verloren gehen.
Nun zum Thema:
Wie ich schon weiter oben empfohlen habe: Reduzier bitte Dein Programm auf nur noch die setenv() und getenv() Funktionen. Dazu natürlich zwischendurch die hilfreichen Kontrollausgaben in die Konsole.Martin
-
So, guten morgen. Habs mal jetzt in nen neues projekt gepackt, das nun nurnoch aus den Zeilen besteht:
#define _WIN32_WINNT 0x0501 #include <conio.h> #include <stdio.h> #include <tchar.h> #include <iostream> #include <Windows.h> int _tmain(int argc, _TCHAR* argv[]) { std::cout << ::SetEnvironmentVariable("GENICAM_ROOT", "C:\\GenICamSDK") << std::endl; //::std::cout << getenv("GENICAM_ROOT") << std::endl; getch(); return 0; }
Die "SetEnvironment..." Zeile liefert schon ne 1 zurück ... und per "set" inner console wurde die Variable auch nicht gesetzt. Dementsprechend scheint es echt der fall zu sein, dass getenv auf eine variable zugreifen will, die es nicht gibt. Die frage ist nun, warum kann die variable nicht geschrieben werden?
-
#define _WIN32_WINNT 0x0501 #include <conio.h> #include <stdio.h> #include <tchar.h> #include <iostream> #include <Windows.h> int _tmain(int argc, _TCHAR* argv[]) { char name[2000]; std::cout << ::SetEnvironmentVariable("GENICAM_ROOT", "C:\\GenICamSDK") << std::endl; std::cout << ::GetEnvironmentVariable("GENICAM_ROOT", name, 2000) << " " << name << std::endl; //std::cout << getenv("GENICAM_ROOT") << std::endl; getch(); return 0; }
1 13 C:\GenICamSDK
"GetEnvironmentVariable" funktioniert... aber warum nicht getenv? Ich weiß nicht, in wie fern die restlichen bibliotheken diese funktion verwenden, weshalb ich lieber auf getenv zurückgreifen möchte.
-
Jetzt verwendest Du die Funktion SetEnvironmentVariable() statt bisher setenv().
Dazu eine kleine Anmerkung (gilt für alle Bereiche der Programmierung):
Verwende nach Möglichkeit immer den jeweils zusammengehörenden Gegenpart, alsoSetEnvironmentVariable() und GetEnvironmentVariable() //das sind Windows-Funktionen
ODER
setenv() und getenv() //das sind CRT-Funktionen
Ansonsten sind unerklärliche Fehlerbilder (oder zumindestens versteckte "Zeitbomben") Deine ständigen Begleiter
Also bitte nicht SetEnvironmentVariable() mit getenv() mischen!
Martin
-
achso, ok, weil im Urprogramm wird es ja so gemacht ... das setenv is ja nur eine funktion im hauptprogramm, und kommt in den bibliotheken garnicht vor...
-
Ohhhh, ist mir gar nicht aufgefallen, daß setenv() nicht "Standard" unter Windows ist
Zumindestens unter Linux gibts aber in stdlib.h die Deklaration von setenv().
Unter Windows hättest Du wahrscheinlich stattdessen _putenv() nehmen sollen (habs eben gegoogelt, deshalb keine Gewähr auf korrekte Funktion).
Unabhängig davon:
Ich persönlich finde die Windows-Funktionen SetEnvironmentVariable() und GetEnvironmentVariable() besser.Freut mich, Dir konnte geholfen werden
Martin
-
Jau cool, funzt
#define _WIN32_WINNT 0x0501 #include <conio.h> #include <stdio.h> #include <tchar.h> #include <iostream> #include <Windows.h> int _tmain(int argc, _TCHAR* argv[]) { char name[2000]; ::putenv("GENICAM_ROOT=C:\\GenICamSDK"); std::cout << getenv("GENICAM_ROOT") << std::endl; getch(); return 0; }
Nu weiß ich, was MS in seiner Doku mit "...These functions are deprecated because more secure versions are available..." zu getenv() meint
Ich danke dir recht herzlich
-
Noch einmal kurz eine sache die mich irritiert - der compiler warnt mich wie folgt:
Warnung 2 Folgende Umgebungsvariablen konnten nicht gefunden werden: $(GENICAM_ROOT) $(GENICAM_MINOR) $(GENICAM_MAJOR) Projekt
aber mindestens GENICAM_ROOT ist doch jetzt gesetzt?
-
Aber doch nicht beim Compilieren, oder?
Sondern erst wenn Dein Programm schon compiliert ist und ausgeführt wurde... und dann auch nur innerhalb Deines Prozesses...Umgebungsvariablen setzrt man in der Systemsteuerung unter "System|Erweitert|Umgebungsvariablen".
-
Kommt als warnung inner Compiler log, ist jetzt aber verschwunden nachdem ich sie per hand eingegeben hab. Danke!