I have a C++ program that syncs files with a remote server when windows xp starts. A function that needs to open a public key file fails at fopen(). When I start the program myself (from within explorer) everything works fine. But when I add a startup key to the registry the function fails.
I traced the code through a debugger and everything's fine until the call to CreateFileA(). CreateFileA returns FILE_NOT_FOUND.
I removed the call to fopen() and replaced it with a call to CreateFileA() directly. Then I changed SECURITY_ATTRIBUTES to NULL after which the call to CreateFileA() works.
The problem is that the 3rd party library I'm using for my encryption needs a FILE* object instead of just the data read from the file. How can I solve my problem?
Here's the code I'm currently using:
if( !GetModuleFileNameA(NULL, Path, MAX_PATH) ){
delete [] buf;
delete [] Path;
return strerror( errno );
}
rPath = Path;
delete [] Path;
ret = rPath.find_last_of( '\\' );
if( ret == string::npos ){
delete [] buf;
return strerror( errno );
}
ret++;
rPath.erase( rPath.begin() + ret, rPath.begin() + rPath.size() - ret );
rPath += "rsa_pub.txt";
if( ( f = fopen( rPath.c_str(), "rb" ) ) == NULL ){ // fails when started from registry
delete [] buf;
return strerror( errno );
}
EDIT:
I found a hackery solution to the problem: if I free the runtime library and then reload it the problem goes away. However this isn't a very elegant solution. Is it perhaps possible to reset the runtime withouth removing and reloading the dll?
Your rPath.erase call doesn't seem to make much sense
rPath.erase( rPath.begin() + ret, rPath.begin() + rPath.size() - ret );
What is that supposed to do?
Here you are using the (iterator, iterator) version of erase here. I beleve you are trying to erase the tail portion of the string beginning from the position ret. In that case I would expect it to look as
rPath.erase( rPath.begin() + ret, rPath.end() );
If you wanted to use the (position, length) version of erase, then it would look as
rPath.erase( ret, rPath.size() - ret );
But your specific usage looks like a weird hybrid of the two. What are you trying to do by that call?
The GetModuleFileNameA probably returns different strings, depending on how you start your program, which is why your code might appear to "work" in some cases.
Related
I have a function that works fine when running inside of the Visual Studio debugging environment (with both the Debug and Release configurations), but when running the app outside of the IDE, just as an end-user would do, the program crashes. This happens with both the Debug and Release builds.
I'm aware of the differences that can exist between the Debug and Release configurations (optimizations, debug symbols, etc) and at least somewhat aware of the differences between running an app inside Visual Studio versus outside of it (debug heap, working directory, etc). I've looked at several of these things and none seem to address the issue. This is actually my first time posting to SO; normally I can find the solution from existing posts so I'm truly stumped!
I am able to attach a debugger and oddly enough I get two different error messages, based on whether I'm running the app on Windows 7 versus Windows 8.1. For Windows 7, the error is simply an access violation and it breaks right on the return statement. For Windows 8.1, it is a heap corruption error and it breaks on the construction of std::ifstream. In both cases, all of the local variables are populated correctly so I know it is not a matter of the function not being able to find the file or read its contents into the buffer data.
Also interestingly, the issue happens only about 20% of the time on Windows 8.1 and 100% of the time on Windows 7, though this may have something to do with the vastly different hardware these OS's are running on.
I'm not sure it makes any difference but the project type is a Win32 Desktop App and it initializes DirectX 11. You'll notice that the file type is interpreted as binary, which is correct as this function is primarily loading compiled shaders.
Here is the static member function LoadFile:
HRESULT MyClass::LoadFile(_In_ const CHAR* filename, _Out_ BYTE** data, _Out_ SIZE_T* length)
{
CHAR pwd[MAX_PATH];
GetCurrentDirectoryA(MAX_PATH, pwd);
std::string fullFilePath = std::string(pwd) + "\\" + filename;
std::ifstream file(fullFilePath, std::ifstream::binary);
if (file)
{
file.seekg(0, file.end);
*length = (SIZE_T)file.tellg();
file.seekg(0, file.beg);
*data = new BYTE[*length];
file.read(reinterpret_cast<CHAR*>(*data), *length);
if (file) return S_OK;
}
return E_FAIL;
}
UPDATE:
Interestingly, if I allocate std::ifstream file on the heap and do not delete it, the issue goes away. There must be something about the destruction of ifstream that is causing an issue in my case.
You don't check the return value of GetCurrentDirectoryA - maybe your current directory name is too long or something?
If you are already using Win32 (not portable!), use GetFileSize to get file size rather than doing seek
Better yet, use boost to write portable code
Switch on all warnings in compiler options
Enable ios exceptions
Okay, I gave up on trying to use ifstream. Apparently I'm not the only one that has this issue...just search "ifstream destructor crash".
Since this app is based on DirectX and will only be run on Windows, I went the Windows API route and everything works perfectly.
Working code, in case anyone cares:
HRESULT MyClass::LoadFile(_In_ const CHAR* filename, _Out_ BYTE** data, _Out_ SIZE_T* length)
{
CHAR pwd[MAX_PATH];
GetCurrentDirectoryA(MAX_PATH, pwd);
string fullFilePath = string(pwd) + "\\" + filename;
WIN32_FIND_DATAA fileData;
HANDLE file = FindFirstFileA(fullFilePath.c_str(), &fileData);
if (file == INVALID_HANDLE_VALUE) return E_FAIL;
file = CreateFileA(fullFilePath.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (file == INVALID_HANDLE_VALUE) return E_FAIL;
*length = (SIZE_T)fileData.nFileSizeLow;
*data = new BYTE[*length];
DWORD bytesRead;
if (ReadFile(file, *data, *length, &bytesRead, NULL) == FALSE || bytesRead != *length)
{
delete[] *data;
*length = 0;
CloseHandle(file);
return E_FAIL;
}
CloseHandle(file);
return S_OK;
}
RESOLVED
I'm trying to make a simple file loader.
I aim to get the text from a shader file (plain text file) into a char* that I will compile later.
I've tried this function:
char* load_shader(char* pURL)
{
FILE *shaderFile;
char* pShader;
// File opening
fopen_s( &shaderFile, pURL, "r" );
if ( shaderFile == NULL )
return "FILE_ER";
// File size
fseek (shaderFile , 0 , SEEK_END);
int lSize = ftell (shaderFile);
rewind (shaderFile);
// Allocating size to store the content
pShader = (char*) malloc (sizeof(char) * lSize);
if (pShader == NULL)
{
fputs ("Memory error", stderr);
return "MEM_ER";
}
// copy the file into the buffer:
int result = fread (pShader, sizeof(char), lSize, shaderFile);
if (result != lSize)
{
// size of file 106/113
cout << "size of file " << result << "/" << lSize << endl;
fputs ("Reading error", stderr);
return "READ_ER";
}
// Terminate
fclose (shaderFile);
return 0;
}
But as you can see in the code I have a strange size difference at the end of the process which makes my function crash.
I must say I'm quite a beginner in C so I might have missed some subtilities regarding the memory allocation, types, pointers...
How can I solve this size issue?
*EDIT 1:
First, I shouldn't return 0 at the end but pShader; that seemed to be what crashed the program.
Then, I change the type of reult to size_t, and added a end character to pShader, adding pShdaer[result] = '/0'; after its declaration so I can display it correctly.
Finally, as #JamesKanze suggested, I turned fopen_s into fopen as the previous was not usefull in my case.
First, for this sort of raw access, you're probably better off
using the system level functions: CreateFile or open,
ReadFile or read and CloseHandle or close, with
GetFileSize or stat to get the size. Using FILE* or
std::filebuf will only introduce an additional level of
buffering and processing, for no gain in your case.
As to what you are seeing: there is no guarantee that an ftell
will return anything exploitable as a numeric value; it could
very well be just a magic cookie. On most current systems, it
is a byte offset into the physical file, but on any non-Unix
system, the offset into the physical file will not map directly
to the logical file you are reading unless you open the file in
binary mode. If you use "rb" to open the file, you'll
probably see the same values. (Theoretically, you could get
extra 0's at the end of the file, but practically, the OS's
where that happened are either extinct, or only used on legacy
mainframes.)
EDIT:
Since the answer stating this has been deleted: you should loop
on the fread until it returns 0 (setting errno to 0 before
each call, and checking it after the return to see whether the
function returned because of an error or because it reached the
end of file). Having said this: if you're on one of the usual
Windows or Unix systems, and the file is local to the machine,
and not too big, fread will read it all in one go. The
difference in size you are seeing (given the numerical values
you posted) is almost certainly due to the fact that the two
byte Windows line endings are being mapped to a single '\n'
character. To avoid this, you must open in binary mode;
alternatively, if you really are dealing with text (and want
this mapping), you can just ignore the extra bytes in your
buffer, setting the '\0' terminator after the last byte
actually read.
I'm doing a system call in c++:
system( "g++ file1.cpp -o test" );
And I'm trying to get the result in the command line into a std::string object. The reason I'm doing that is to analyze the output of g++ in the case where g++ fails because there is an error in the cpp.
Here's the method I've built for that:
std::string CmdLineCall( std::string cmd )
{
FILE* pipe = _popen( cmd.c_str(), "r");
if( pipe == NULL )
{
return "error";
}
char* buffer;
long bufferSize = cmd.size();
size_t code;
std::string result;
buffer = ( char* )malloc( sizeof( char ) * bufferSize );
if( buffer == NULL )
{
return "error";
}
code = fread( buffer, 1, sizeof( buffer ), pipe );
if( code != bufferSize )
{
return "error";
}
result = buffer;
return result;
}
I've debugged it and it goes all the way to the end but result = "".
I've tried with a simple system( "pause" ) command and it works, but it doesn't work.
Can it have something to do with the fact that the g++ call fails because my cpp file is flawed?
Thanks
Using system() is probably not the best choice for this. You might have better results with popen(), since that lets you read the standard output of your command -- but I suspect that won't be enough here either (as I assume the compiler may also print to stderr and popen() doesn't give you that).
Your best bet is to provide your own variant of popen that includes support for both stdout and stderr (and if you search for "popen source" I'm sure you'll have a good starting point).
Edit: on a re-read of your post, I see you are using popen()… so I'm a bit confused about where system() comes into play since you wouldn't use both of them. Regardless, I still feel the problem is that stderr is important and popen() isn't giving that to you, so you'll need to go get it yourself; you could do that by rewriting popen() or you could just redirect your own stderr to the input channel of a pipe before you call popen().
In the following code if I comment out the call to "GetCurrentDirectory" everything works fine, but if I don't then the code breaks after it, no child windows show up, but the program don't crash. The compiler doesn't give any error.
char *iniFilePath;
int lenWritten = GetCurrentDirectory( MAX_PATH, iniFilePath );
if( lenWritten )
{
lstrcat( iniFilePath, iniFileName.c_str() );
char *buffer;
GetPrivateProfileString( iniServerSectionName.c_str(), serverIp.c_str(), "", buffer, MAX_PATH, iniFilePath );// server ip
MessageBox( 0, buffer, 0, 0 );
}
else
{
MessageBox( 0,0,0,0 );
}
iniFilePath is an unintialised pointer which GetCurrentDirectory() is attempting to write to, causing undefined behaviour. GetCurrentDirectory() does not allocate a buffer for the caller: it must be provided.
Change to:
char iniFilePath[MAX_PATH]; // or similar.
Instead of using lstrcat(), which has Warning Do not use message on its reference page, construct the path use a std::string instead to avoid potential buffer overruns:
const std::string full_file_path(std::string(iniFilePath) + "/" + iniFileName);
Note similar issue with buffer, as pointed out by Wimmel.
I would do this in order to get the current directory -
int pathLength = GetCurrentDirectory(0, NULL);
std::vector<char> iniFilePath(pathLength);
GetCurrentDirectory(pathLength, iniFilePath.data());
Note however that this won't be thread safe as the directory could change from another thread between the two calls but as far as I know few programs change the current directory so it's unlikely to be an issue.
I'm running some commands with the C++ system() function:
int system ( const char * command );
How can I collect the standard output from the issued commands?
To be specific, I want to collect the output of the issued command (for example, the directory listing output from issuing the dir command).
Are you looking for returned value (as in "exit status") of the executed command, or for its output (as in "what did it print")?
If the latter, use popen() and pclose() instead.
If the former, look at the return value from system() (and use the documentation for waitpid() to interpret it).
system() returns an int, so just grab it: int rvalue = system(command);
I believe the exact details of what system() will return are system-specific, though.
There are typically two ways for a system program to "return" a value: by writing to stdout, and by returning a status integer at the end of the program. (there are often more ways to return results, eg. by writing to a file or into a database, but I assume those are out of scope here).
For receiving the status code, just check the return value of the system function.
For receiving the output, either redirect it into a file, and read the file afterwards, or use popen.
The return value of system is (ironically) system-dependent, but in POSIX systems (including Linux, etc), it's the same as for wait -- low 8 or 16 bits are the exit status of the child (probably what you mean by "value returned by"), higher bits indicating what kind of signal terminated the child, if any. The URL to the manpage I've given supplies the preprocessor macros you can use to pry apart that return value!
There is no such thing as a "return string" of a program, as you've now clarified in a comment is what you desire; as another answer already mentioned, if you want the text which gets output by the other program, you should use popen instead of system.
Inspired by bmorin's attempt, but working and tested, this snippet will take a char* command and return a char* containing the results of executing that command...
// Calling function must free the returned result.
char* exec(const char* command) {
FILE* fp;
char* line = NULL;
// Following initialization is equivalent to char* result = ""; and just
// initializes result to an empty string, only it works with
// -Werror=write-strings and is so much less clear.
char* result = (char*) calloc(1, 1);
size_t len = 0;
fflush(NULL);
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return NULL;
}
while(getline(&line, &len, fp) != -1) {
// +1 below to allow room for null terminator.
result = (char*) realloc(result, strlen(result) + strlen(line) + 1);
// +1 below so we copy the final null terminator.
strncpy(result + strlen(result), line, strlen(line) + 1);
free(line);
line = NULL;
}
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
return result;
}
I looked into just editing bmorin's code, but would have had to change most lines, so a separate answer seemed more appropriate. Apologies if not. (Amongst other problems, bmorin's code didn't actually accumulate the lines; it printed them to stdout, where I presume they would not be wanted, since system() would have done that; and it returned void in one error path, when the function must return a char*, so the code wouldn't compile. Perhaps most egregious, it freed the result just before returning it.)
system() is declared and defined in libc. You can either read the first link I provided, or do man system at a command prompt in your shell.
I suggest the popen() functions, as said by other people as well,
but this problem is platform specific. the popen() function is
available on operating systems that use the POSIX API. I am not
sure if this command would work on other APIs like WIN32
Here is a code snippet (in plain C) executing a command with popen and returning its output:
char* exec(const char* command) {
FILE* fp;
char* result = NULL;
size_t len = 0;
fflush(NULL);
fp = popen(command, "r");
if (fp == NULL) {
printf("Cannot execute command:\n%s\n", command);
return;
}
while(getline(&result, &len, fp) != -1) {
fputs(result, stdout);
}
free(result);
fflush(fp);
if (pclose(fp) != 0) {
perror("Cannot close stream.\n");
}
return result;
}