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.
Related
While writing some code to update a position in a binary file I noticed something strange. Consider this example code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
char tmp;
string s;
fstream fs;
fs.open("test.txt", fstream::out);
fs << "blub" << endl;
fs.close();
fs.open("test.txt", fstream::in);
fs >> s;
cout << s << endl;
fs.close();
fs.open("test.txt", ios::in|ios::out|ios::binary);
if (!fs.is_open() || !fs.good())
cerr << "could not open!" << endl;
fs.read(&tmp, 1);
fs.read(&tmp, 1);
//fs.tellg(); //<-- required to fix for old g++?
const char *c = "ah";
fs.write(&c[0], 1);
fs.write(&c[1], 1);
fs.close();
fs.open("test.txt", fstream::in);
fs >> s;
cout << s << endl;
}
In recent g++ versions (at least with 6.2.1), I can just read and then write some bytes without problems - In the example you get the correct output:
blub
blah
Then I compiled the code with g++ 4.7.2 and suddenly the update has no effect, i.e. the second output is still "blub", unless I add fs.tellg() or fs.tellp(). I've found this question, but as I understand, this is a limitation under Windows, but I am working under Linux.
Now I wonder, is this a bug in the old g++ or am I doing it wrong and was just lucky with the modern g++ version, where it just works? Second question, why does asking for the current position fix it?
Thanks in advance!
Now I wonder, is this a bug in the old g++
No, there is no bug in g++ in this regard.
or am I doing it wrong
Yes. This is explained in the answer that you linked.
... output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end- of-file.
Which is from C standard but made relevant by:
The restrictions on reading and writing a sequence controlled by an object of class basic_filebuf are the same as for reading and writing with the Standard C library FILEs.
There is a bug, but it is in your code. Your program doesn't meet the requirements laid out by the standard.
but as I understand, this is a limitation under Windows
That may possibly be the case, but more generally the limitation is in C++ (and C) specification. Whether a standard library has the limitation has no effect on whether the library is standard compliant. Any code that depends on the non-existence of the limitation is not compliant with the standard.
and was [I] just lucky with the modern g++ version
One might say that you were unlucky. It was a stroke of luck when the program didn't work and you discovered the bug.
Second question, why does asking for the current position fix it?
I doubt that tellg is sufficient to make your program compliant with the standard. So, I would say that it "fixes" the program by chance.
You should probably be using std::flush(fs); instead.
this would mean that the NEW version is LESS standard compliant?
No, both versions of g++ are equally compliant in this regard. Your program isn't.
I try to do the most basic regex example in C++ using the default lib, and I keep getting either crashes or incoherent behavior.
// with -std=c++11
#include <regex>
using namespace std;
int main()
{
// Copied from the documentation, this one works
if (std::regex_match ("subject", std::regex("(sub)(.*)") ))
std::cout << "string matched\n";
// The most simple example I could try, crash with "regex_error"
if (std::regex_match ("99", std::regex("[0-9]*") ))
std::cout << "integer matched\n";
}
I've tried multiple syntaxes and flags, but nothing seems to work. Since my code seems to be matching all the examples I can find, I'm struggling to see what I'm missing.
As #Wiktor Stribiżew stated, it was just my compiler being too old. Updating the compiler (from gcc 4.1 to gcc 4.9) solved the problem!
This code seemed to work ok in (ubuntu trusty) versions of gcc and clang, and in Win 7 on a VM via mingw... Recently I upgraded to Wily and builds made with clang crash consistently here.
#include <iostream>
#include <locale>
#include <string>
int main() {
std::cout << "The locale is '" << std::locale("").name() << "'" << std::endl;
}
Sometimes its a gibberish string followed by Aborted: Core dumped and sometimes its invalid free.
$ ./a.out
The locale is 'en_US.UTF-8QX�у�X�у����0�����P�����\�(��\�(��\�(��h��t�������������y���������ț�ԛ�������en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_UP����`�������������������������p�����������#��������������`�������������p��������������������#��#��#��`��������p������������0��P��p���qp��!en_US.UTF-8QЈ[�����\�(��\�(��\�(�����������#�� �����P�����0�����P�����\�(��\�(��\�(��Ȣ�Ԣ����������������(��4��#��L��en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8!�v[��������������#�� �����P�����0�����P�����\�(��\�(���(��h��t��������������������Ȥ�Ԥ�������en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8!��[�� ����[�������7����7��.,!!x�[��!��[��!�[��#�����������#�� �����P�����0�����P�����\�(��\�(��\�(��(��4��#��L��X��d��p��|������������n_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8ѻAborted (core dumped)
$ ./a.out
The locale is 'en_US.UTF-8QX\%�QX\%�Q�G�0H��H�PI��I�\:|�Q\D|�Q\>|�QhK�tK��K��K��K��K��Q�K��K��K��K��K��K�en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8ѻ
*** Error in `./a.out': free(): invalid pointer: 0x0000000000b04a98 ***
Aborted (core dumped)
(Both program outputs above were abbreviated greatly or they would not fit in this question.)
I also got an invalid free on Coliru with it as well.
But this is very similar to example code on cppreference:
#include <iostream>
#include <locale>
#include <string>
int main()
{
std::wcout << "User-preferred locale setting is " << std::locale("").name().c_str() << '\n';
// on startup, the global locale is the "C" locale
std::wcout << 1000.01 << '\n';
// replace the C++ global locale as well as the C locale with the user-preferred locale
std::locale::global(std::locale(""));
// use the new global locale for future wide character output
std::wcout.imbue(std::locale());
// output the same number again
std::wcout << 1000.01 << '\n';
}
Actually that code crashes Coliru also... :facepalm:
More crashes of similar code from Coliru.
Is this a bug in the c++ library used by clang, or is this code defective?
Note also: These crashes seem to be restricted to the C++ api, if you use <clocale> instead things seem to work okay, so it may just be some trivial problem in the C++ bindings over this?
Variations using setlocale: 1 2 3
Looks like this is caused by libstdc++'s ABI change in its basic_string, which was needed for C++11 conformance. To manage this transition, GCC added the abi_tag attribute, which changes the mangled name of functions so that functions for the new and old ABI can be distinguished, even if the change wouldn't otherwise affect the mangled name (e.g. the return type of a function).
This code
#include <locale>
#include <string>
int main() {
std::locale().name();
}
on GCC emits a call to _ZNKSt6locale4nameB5cxx11Ev, which demangles to std::locale::name[abi:cxx11]() const, and returns a SSO string with the new ABI.
Clang, on other other hand, doesn't support the abi_tag attribute, and emits a call to _ZNKSt6locale4nameEv, which demangles to simply std::locale::name() const - which is the version returning a COW string (the old ABI).
The net result is that the program ends up trying to use a COW string as an SSO string when compiled with Clang. Havoc ensues.
The obvious workaround is to force the old ABI via -D_GLIBCXX_USE_CXX11_ABI=0.
I think the "" parameter might be corrupting something. I don't think it's a legal argument?
To verify it's nothing else, try running this:
#include <iostream>
#include <locale>
int main() {
std::locale("").name();
}
It compiles and runs just fine with GCC:
g++ -Wall -pedantic locale.cpp
<= No errorrs, no warnings
./a.out
The locale is 'en_US.UTF-8'
<= Expected output
ADDENDUM:
Exactly the same with MSVS 2013 - no errors or warnings compiling; no errors running:
locale.cpp =>
#include <iostream>
#include <locale>
#include <string>
int main() {
std::cout << "The locale is '" << std::locale("").name() << "'" << std::endl;
}
Output =>
locale
The locale is 'English_United States.1252'
this is the code i am trying to compile, got it from another forum somewhere.
// to_string example
#include <iostream> // std::cout
#include <string> // std::string, std::to_string
int main ()
{
std::string pi = "pi is " + std::to_string(3.1415926);
std::string perfect = std::to_string(1+2+4+7+14) + " is a perfect number";
std::cout << pi << '\n';
std::cout << perfect << '\n';
return 0;
}
I am getting the error:
'to_string' is not a member of 'std'
I have read in other forums to select the flags "Have g++ follow the c++11 ISO language standard [-std=c++11]" and i have and it still doesn't work.
Any help would be greatly appreciated
I am using the GNU GCC Compiler
and code::Blocks 12.11
MinGW-w64 added support for the necessary functionality since GCC 4.8, so make sure you are using at least version 4.8 GCC from MinGW-w64.
You can get one from here, although Code::Blocks should come with a TDM GCC toolchain which should work if it's the latest (because it's GCC 4.8.1 at the time of writing).
i also encounter this error in codeblocks-13.12mingw-setup-TDM-GCC-481.exe(built on 27 Dec 2013).
it seems a bug with tdmgcc4.8.1. maybe the newest tdmgcc whill fixed it.
https://stackoverflow.com/questions/21626866/c-elipse-cdt-getting-to-string-was-not-declared-in-this-scope-with-tdm-gcc-6
the reason of above list should be the same as ours.
==============================
The std::to_string functions are guarded by !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF). MinGW defines this symbol as 1 in its os_defines.h, so you know, we cannot use it in mingw.
Easiest way to deal with this error is:
double piValue = 3.1415;
char piBuffer[8];
sprintf(piBuffer, "%f", piValue);
string pi(piBuffer);
I know there's been a handful of questions regarding std::ifstream::open(), but the answers didn't solve my problem. Most of them were specific to Win32, and I'm using SDL, not touching any OS-specific functionality (...that's not wrapped up into SDL).
The problem is: std::ifstream::open() doesn't seem to work anymore since I've switched from Dev-C++ to Code::Blocks (I've been using the same MinGW-GCC back-end with both), and from Windows XP to Vista. (It also works perfectly with OS X / xcode (GCC back-end).)
My project links against a static library which #includes <string>, <iostream>, <fstream> and <cassert>, then a call is made to functionality defined in the static library, which in turn calls std::ifstream::open() (this time, directly). Following this, the stream evaluates to false (with both the implicit bool conversion operator and the good() method).
Code:
#include "myStaticLibrary.hpp"
int main(int argc, char **argv)
{
std::string filename("D:/My projects/Test/test.cfg");
std::cout << "opening '" << filename << "'..." << std::endl;
bool success(false);
// call to functionality in the static library
{
std::ifstream infile(filename.c_str());
success = infile.good();
// ...
}
// success == false;
// ...
return 0;
}
stdcout.txt says:
opening 'D:/My projects/Test/test.cfg'...
When I open stdcout.txt, and copy-paste the path with the filename into Start menu / Run, the file is opened as should be (I'm not entirely sure how much of diagnostic value this is though; also, the address is converted to the following format: file:///D:/My%20projects/test/test.cfg).
I've also tried substituting '/'s with the double backslash escape sequence (again, slashes worked fine before), but the result was the same.
It is a debug version, but I'm using the whole, absolute path taken from main()'s argv[0].
Where am I going wrong and what do I need to do to fix it?
Please create a minimal set that recreates the problem. For example, in your code above there's parsing of argv and string concatentation, which do not seem like a necessary part of the question. A minimal set would help you (and us) see exactly what's going wrong, and not be distracted by questions like "what's GetPath()?".
Try to do this instead of assert(infile.good()):
assert(infile);
I have overseen the importance of the fact that the function in question has close()d the stream without checking if it is_open().
The fact that it will set the stream's fail_bit (causing it to evaluate to false) was entirely new to me (it's not that it's an excuse), and I still don't understand why did this code work before.
Anyway, the c++ reference is quite clear on it; the problem is now solved.
The following code:
#include <string>
#include <iostream>
#include <fstream>
#include <assert.h>
using namespace std;;
int main(int argc, char **argv)
{
std::string filename("D:/My projects/Test/test.cfg");
std::cout << "opening '" << filename << "'..." << std::endl;
std::ifstream infile(filename.c_str());
assert(infile.good()); // fails
return 0;
}
works fine on my Windows system using MinGW g++ 4.4.0, if I create the required directory structure. Does the file test.cfg actually exist? If you are opening a stream for input, it wioll fail if the file is not there.
Edit: To remove any DevC++ to CB issues:
build using command line only
make sure you rebuild the static library too