I've been a C++ developer since it arrived. All was on windows, and I haven't touched it in about 6 years.
Now I'm trying to get an old code-base working using VS Code on my Mac. I'm using clang++ with c++17.
This problem is vexing; I've seen many other posts with the same issue, but the problem always seemed to be something in the code.
Note: this code worked fine with C++11 on Windows.
To simplify, I copied the code to execute right at the top of main. Here is is:
ifstream file("assets/textures/blocks.txt", ios::in);
if( file.is_open() ) {
string s;
getline(file, s); // <-- This line causes the error.
cout << s << endl;
}
As this code worked elsewhere, I assume I've got a setup or environment problem and am looking for hints towards what to check on.
Thank you for any help!
An update:
Thank you. I paired the program down and tried a few things. Here's the deal:
If I leave all my files to be compiled, but replace main.cpp with the below code, the cout line generates the same exception.
If I cull all the unused files, the code works.
Something in some other file is somehow breaking the stream code. I'm clueless.
#include <iostream>
#include <istream>
using namespace std;
int main() // int argc, char** argv)
{
cout << "Hello World" << endl;
}
I should add: this is a GLFW 3D game engine app. It does not subclass or interact with any stream in any way other than the most basic file read/write operations.
I'm basically looking for a C++ version of fdopen(). I did a bit of research on this and it is one of those things that seems like it should be easy, but turns out to be very complicated. Am I missing something in this belief (i.e. it really is easy)? If not, is there a good library out there somewhere to handle this?
EDIT: Moved my example solution to a separate answer.
From the answer given by Éric Malenfant:
AFAIK, there is no way to do this in
standard C++. Depending on your
platform, your implementation of the
standard library may offer (as a
nonstandard extension) a fstream
constructor taking a file descriptor
as input. (This is the case for
libstdc++, IIRC) or a FILE*.
Based on above observations and my research below there's working code in two variants; one for libstdc++ and another one for Microsoft Visual C++.
libstdc++
There's non-standard __gnu_cxx::stdio_filebuf class template which inherits std::basic_streambuf and has the following constructor
stdio_filebuf (int __fd, std::ios_base::openmode __mode, size_t __size=static_cast< size_t >(BUFSIZ))
with description This constructor associates a file stream buffer with an open POSIX file descriptor.
We create it passing POSIX handle (line 1) and then we pass it to istream's constructor as basic_streambuf (line 2):
#include <ext/stdio_filebuf.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ofstream ofs("test.txt");
ofs << "Writing to a basic_ofstream object..." << endl;
ofs.close();
int posix_handle = fileno(::fopen("test.txt", "r"));
__gnu_cxx::stdio_filebuf<char> filebuf(posix_handle, std::ios::in); // 1
istream is(&filebuf); // 2
string line;
getline(is, line);
cout << "line: " << line << std::endl;
return 0;
}
Microsoft Visual C++
There used to be non-standard version of ifstream's constructor taking POSIX file descriptor but it's missing both from current docs and from code. There is another non-standard version of ifstream's constructor taking FILE*
explicit basic_ifstream(_Filet *_File)
: _Mybase(&_Filebuffer),
_Filebuffer(_File)
{ // construct with specified C stream
}
and it's not documented (I couldn't even find any old documentation where it would be present). We call it (line 1) with the parameter being the result of calling _fdopen to get C stream FILE* from POSIX file handle.
#include <cstdio>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ofstream ofs("test.txt");
ofs << "Writing to a basic_ofstream object..." << endl;
ofs.close();
int posix_handle = ::_fileno(::fopen("test.txt", "r"));
ifstream ifs(::_fdopen(posix_handle, "r")); // 1
string line;
getline(ifs, line);
ifs.close();
cout << "line: " << line << endl;
return 0;
}
AFAIK, there is no way to do this in standard C++. Depending on your platform, your implementation of the standard library may offer (as a nonstandard extension) a fstream constructor taking a file descriptor (This is the case for libstdc++, IIRC) or a FILE* as an input.
Another alternative would be to use a boost::iostreams::file_descriptor device, which you could wrap in a boost::iostreams::stream if you want to have an std::stream interface to it.
There's a good chance your compiler offers a FILE-based fstream constructor, even though it's non-standard. For example:
FILE* f = fdopen(my_fd, "a");
std::fstream fstr(f);
fstr << "Greetings\n";
But as far as I know, there's no portable way to do this.
Part of the original (unstated) motivation of this question is to have the ability to pass data either between programs or between two parts of a test program using a safely created temporary file, but tmpnam() throws a warning in gcc, so I wanted to use mkstemp() instead. Here is a test program that I wrote based on the answer given by Éric Malenfant but using mkstemp() instead of fdopen(); this works on my Ubuntu system with Boost libraries installed:
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
using boost::iostreams::stream;
using boost::iostreams::file_descriptor_sink;
using boost::filesystem::path;
using boost::filesystem::exists;
using boost::filesystem::status;
using boost::filesystem::remove;
int main(int argc, const char *argv[]) {
char tmpTemplate[13];
strncpy(tmpTemplate, "/tmp/XXXXXX", 13);
stream<file_descriptor_sink> tmp(mkstemp(tmpTemplate));
assert(tmp.is_open());
tmp << "Hello mkstemp!" << std::endl;
tmp.close();
path tmpPath(tmpTemplate);
if (exists(status(tmpPath))) {
std::cout << "Output is in " << tmpPath.file_string() << std::endl;
std::string cmd("cat ");
cmd += tmpPath.file_string();
system(cmd.c_str());
std::cout << "Removing " << tmpPath.file_string() << std::endl;
remove(tmpPath);
}
}
It actually is quite easy. Nicolai M. Josuttis has released fdstream in conjunction with his book The C++ Standard Library - A Tutorial and Reference. You can find the 184 line implementation here.
I've tried the solution proposed above for libstdc++ by Piotr Dobrogost, and found that it had a painful flaw: Due to the lack of a proper move constructor for istream, it's very difficult to get the newly constructed istream object out of the creating function. Another issue with it is that it leaks a FILE object (even thought not the underlying posix file descriptor). Here's an alternative solution that avoids these issues:
#include <fstream>
#include <string>
#include <ext/stdio_filebuf.h>
#include <type_traits>
bool OpenFileForSequentialInput(ifstream& ifs, const string& fname)
{
ifs.open(fname.c_str(), ios::in);
if (! ifs.is_open()) {
return false;
}
using FilebufType = __gnu_cxx::stdio_filebuf<std::ifstream::char_type>;
static_assert( std::is_base_of<ifstream::__filebuf_type, FilebufType>::value &&
(sizeof(FilebufType) == sizeof(ifstream::__filebuf_type)),
"The filebuf type appears to have extra data members, the cast might be unsafe");
const int fd = static_cast<FilebufType*>(ifs.rdbuf())->fd();
assert(fd >= 0);
if (0 != posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
ifs.close();
return false;
}
return true;
}
The call to posix_fadvise() demonstrates a potential use. Also note that the example uses static_assert and using which are C++ 11, other than that it should build just fine in C++ 03 mode.
Another non-portable solution is to use mmap (or its Windows' analogue) and then construct std::iostream from a pointer that mmap gave like so.
Yeah, it does not construct exactly an std::fstream, but this requirement rarely needs to be met because every piece of code should depend on stream interfaces (e.g. std::istream) rather than on their implementations.
I think this solution is more portable than use of STL implementation-specific hacks, because this way you only depend on an operating system, rather than on a specific implementation of STL for the same OS.
My understanding is that there is no association with FILE pointers or file descriptors in the C++ iostream object model in order to keep code portable.
That said, I saw several places refer to the mds-utils or boost to help bridge that gap.
Picking up C++ and having a go at it on OS X 10.9 using XCode 5.0.2 and using Alex Allain as reference.
The following code compiles just fine and outputs correctly
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string user_first_name = "test";
std::cout << user_first_name << "\n";
return 0;
}
When I add a getline function, code appears to compile but with no output.
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string user_first_name = "test";
std::getline( std::cin, user_first_name, '\n' );
std::cout << user_first_name << "\n";
return 0;
}
In fact debug navigator has memory filling up with bars (although actual memory use is fixed at 276 KB). Why am I getting stumped on such a simple thing/concept?
I did a bit of digging around and its quite likely this is related to a text encoding issue. I'm using defaults which is Unicode (UTF-8). Encoding is not something I'm familiar with, never something I had to deal with when learning on Windows. How do I get past this?
I can't comment regarding the use of XCode or OS X, but it was my understanding that std::cin always gives you a narrow (single-byte) character stream. In Windows (at least with Visual Studio), I think it works whether you compile for UTF8 (single-byte for all ASCII characters) or UTF16 (2-bytes for all ASCII characters). The runtime library presumably does the conversion for you as necessary.
I'm not sure what "filling up with bars" means, but maybe it's just that you're looking at uninitialized memory. If you think that it is an encoding issue, perhaps try using wstring/wcin instead of string/cin and see if that helps.
I have a Visual Studio 2008 C++ project for Windows CE 5 where I would like the currently running executable to modify itself.
Specifically, I would like to be able to read/write some data stored within the exe file itself. I do not need (or wish to) modify executable code.
In regular windows, I could use a string resource and the UpdateResource function, but that doesn't exist in WinCE.
CreateFile, unfortunately, fails because the file is already in use.
Does anybody have any other suggestions?
First, why do you need to do this? You should be able to do this with other methods.
I'm not particularly familiar with Windows-CE, but if you need to, you can probably copy the file, edit the copy, delete the first, and then run the other. That's an inefficient way, but if you only need to do it once or twice in the span of the program and speed isn't a concern, I guess you could do it:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char * argv[]) {
// Check if this IS the copy:
if (argv[0].find(argv[1]) != string::npos) {
system("taskkill -IM myOLDfile.exe"); // Stop the old one running,
system("del myOLDfile.exe"); // Then delete it.
}
ifstream myself(argv[0]); // argv[0] is the program itself
string fullcode;
string line;
if (file.is_open()) {
while (file.good()) {
getline(myself, line);
line.append("\n");
fullcode.append(line);
}
}
myself.close();
// Do whatever you need to do to the code here.
ofstream newcode("myNEWfile.exe");
newcode.write(fullcode);
newcode.close();
system("myNEWfile.exe myNEWfile.exe"); // Starts new file. Also, not a typo.
}
Good luck on your project!
I'm using _GLIBCXX_DEBUG mode to help find errors in my code but I'm having a problem which I think is an error in the library, but hopefully someone can tell me I'm just doing something wrong. Here is a short example which repro's the problem:
#define _GLIBCXX_DEBUG
#include <iostream>
#include <sstream>
int main (int argc, const char * argv[]) {
std::ostringstream ostr;
ostr << 1.2;
std::cout << "Result: " << ostr.str() << std::endl;
return 0;
}
If I comment out the #define then the output is (as expected):
Result: 1.2
With the _GLIBCXX_DEBUG define in place however the output is simply:
Result:
I've tracked this down to the _M_num_put field of the stream being left as NULL, which causes an exception to be thrown (and caught) in the stream and results in no output for the number. _M_num_put is supposed to be a std::num_put from the locale (I don't claim to understand how that's supposed to work, it's just what I've learned in my searching so far).
I'm running this on a Mac with XCode and have tried it with both "LLVM GCC 4.2" and "Apple LLVM Compiler 3.0" as the compiler with the same results.
I'd appreciate any help in solving this. I want to continue to run with _GLIBCXX_DEBUG mode on my code but this is interfering with that.
Someone else has seen this over at cplusplus.com
and here at stackoverflow, too.
Consensus is that it is a known bug in gcc 4.2 for Mac OS, and since that compiler is no longer being updated, it is unlikely to ever be fixed.
Seems to me that you can either (1) use LLVM, or (2) build your own GCC and use it.