I have spent 2 days chasing an issue involving C++ container, std::list, and C-Style structs. Is the following undefined behavior (Note the type for the std::list parameter)?
#include <list>
#include <iostream>
using std::cout;
using std::endl;
struct Point_Struct
{
int x;
int y;
};
typedef struct Point_Struct Point;
int main()
{
std::list<Point> line;
Point p;
p.x = 3;
p.y = 10;
line.push_back(p);
cout << "Size of container: " << line.size() << "\n";
// Here's the issue:
line.pop_back();
// The size should be zero.
cout << "Size of container after pop_back(): " << line.size() << "\n";
return 0;
}
I ran this on Visual Studio 2017 and I get an exception error, 0xC0000005, (memory access) on the call to pop_back.
The exception is also thrown on any method that changes the ordering of the items in the list, such as assignment and sort.
If I change the type of line to std::list<Point_Struct>, there are no exceptions thrown.
Note: The issue was found in a larger program. The code above illustrates the root cause of the issue: std::list<typedef struct> vs. std::list<struct>
Note: The exception is thrown in VS2017 debug mode but not in release mode.
Sorry, but multiple questions follow:
Is there anything in standard C++ (11 or later) declaring undefined
behavior for using a typedef instead of a struct as the template
parameter for std::list?
Would this be a Visual Studio bug?
I haven't tried on G++ or other compilers.
Edit 1: VS2017 version info
Microsoft Visual Studio Professional 2017
Version 15.9.14
Installed product: Visual C++ 2017 - 00369-60000-00001-AA071
Compilation Info
Configuration: Debug
Platform: Win32
Warning Level: Level3 (/W3)
Optimization: Disabled (/Od)
Enable C++ Exception: Yes (/EHsc)
Basic Runtime Checks: Both (/RTC1)
Disable Language Extensions: No
Conformance mode: No
Platform
Platform: Windows 7
I compiled and ran your code with g++ 11 in Eclipse (Ubuntu 18) and it worked perfectly,
Output:
Size of container: 1
Size of container after pop_back(): 0
Have you tried/is it possible to swap typedef for using? This might fix it:
#include <list>
#include <iostream>
using std::cout;
using std::endl;
struct Point_Struct
{
int x;
int y;
};
using Point = Point_Struct;
int main()
{
std::list<Point> line;
Point p;
p.x = 3;
p.y = 10;
line.push_back(p);
cout << "Size of container: " << line.size() << "\n";
// Here's the issue:
line.pop_back();
// The size should be zero.
cout << "Size of container after pop_back(): " << line.size() << "\n";
return 0;
}
Related
I am facing a problem with shrink_to_fit() function of STL C++. The problem is which I use it, the compiler gives error "Method 'shrink_to_fit' could not be resolved" on Eclipse Luna (32 bit) with MinGW compiler but the same program works fine in Dev C++.
Image of the program:
Error:
Compiler do not recommend shrink_to_fit() after using dot(.):
Original code:
#include <iostream>
#include <vector>
using namespace std;
int main(void) {
vector<int> v(128);
cout << "Initial capacity = " << v.capacity() << endl;
v.resize(25);
cout << "Capacity after resize = " << v.capacity() << endl;
v.shrink_to_fit();
cout << "Capacity after shrink_to_fit = " << v.capacity() << endl;
return 0;
}
Please let me know is this my fault or IDE's.
P.S. I am using C++14.
It works fine for me (with -std=c++11 flag, and MinGW distro from https://nuwen.net/mingw.html#install) on
Eclipse IDE for C/C++ Developers,
Version: 2019-09 R (4.13.0)
Build id: 20190917-1200
OS: Windows 10, v.10.0, x86_64 / win32
Java version: 13.0.1
as well as on Linux (with -std=c++11 flag and GCC 7.4.0 compiler). It could be a problem with your IDE, compiler (with right flag) or STL implementation. There can't be a 4th reason in my view.
Works fine for me.
Try compile 'by hand' to find out if it is about the ide:
g++ foo.cpp -o foo
./foo
I'm not very used to using weak_ptr and I'm facing a quite confusing situation. I'm using Intel XE 2019 Composer update 5 (package 2019.5.281) in combinaison with Visual Studio 2019 ver. 16.2.5. I compile in 64-bit. I use the standard C++ 17.
Here is the code for my spike solution:
#include <memory>
#include <iostream>
using namespace std;
int main( int argc, char* argv[] )
{
shared_ptr<int> sp = make_shared<int>( 42 );
cout << "*sp = " << *sp << endl;
weak_ptr<int> wp = sp;
cout << "*sp = " << *sp << ", *wp = " << *wp.lock() << endl;
wp.reset();
cout << "*sp = " << *sp << endl;
return 0;
}
The output I expected to have is:
*sp = 42
*sp = 42, *wp = 42
*sp = 42
...but here is what I obtained:
*sp = 42
*sp = 42, *wp = 42
*sp = -572662307
What is goin on? Is it normal for the shared_ptr to be modified/invalidated when the/an associated weak_ptr is reset? I'm a little confused about the results I obtained. To say the truth I didn't expect this result...
EDIT 1
While the bug occurs in 64-bit configuration, it doesn't in 32-bit. In this later configuration, the result is what is expected.
EDIT 2
The bug occurs only in Debug. When I build in Release, I get the expected result.
It appears it is a real bug on Intel ICC side; I have reported it.
Thanks again for helping me to pin-point this problem.
It looks like a bug in debug library, with sentinel values.It's easy to check, by using line I mentioned:
int i = 1; cout << i << " " << ++i << endl;
If output is 2 2 instead of 1 2, then compiler is not compliant and possibly still considers such case an UB. Sentinel values may be used erroneously in this case with call of reset(). Similar thing happens with deleting object created by placement new within preallocated static buffer, in debug mode it gets overwritten by some implementations with sentinel values.
I'm trying to learn about vectors in C++, but just trying to declare one throws a runtime error in NetBeans.
Error: Run failed (exit value -1, 073, 741, 511, total time 51 ms)
PS: The code works perfectly in Eclipse.
#include <iostream>
#include <vector>
using namespace std;
int main() {
// create a vector to store int
vector<int> vec;
int i;
// display the original size of vec
cout << "vector size = " << vec.size() << endl;
// push 5 values into the vector
for (i = 0; i < 5; i++) {
vec.push_back(i);
}
// display extended size of vec
cout << "extended vector size = " << vec.size() << endl;
// access 5 values from the vector
for (i = 0; i < 5; i++) {
cout << "value of vec [" << i << "] = " << vec[i] << endl;
}
// use iterator to access the values
vector<int>::iterator v = vec.begin();
while (v != vec.end()) {
cout << "value of v = " << *v << endl;
v++;
}
return 0;
}
I have tested on my system (latest GCC and NB dev build) and it works without any problem. The desired output is shown. It also runs fine from command line.
Therefore I assume it's more a configuration or system related problem. But without any further informations it's impossible to find the root cause.
More information please:
What OS / Environment are you using?
What Compiler (and versions) do you have?
What version of Netbeans do you use?
Do other project's work?
Here's some first aid you can try:
Create a new C++ Project (C++ Application). It already includes a blank main() function. Run this and check if there's still an error
Create a simple .cpp file and build it from command line (don't involve any IDE). Does it work this way?
Build and your source file without IDE. From Commandline: g++ <your filename>.cpp
Review your compiler settings (Tools -> Options -> C/C++ at Build Tools). Especially use the Version button and check if everything is right.
Windows only: Make sure you have the correct make executable selected in the compiler settings
Have a look at the IDE's log (View -> IDE Log). Are there any problems mentioned?
Run in Debug without any breakpoint. This is going to stop the execution on any runtime error.
The following code acts differently after being compiled in linux and Visual Studio 2015.
#include <map>
#include <iostream>
using namespace std;
int main(void)
{
map<int, int> map1;
int keyCount = 2;
for (int i = 0; i < keyCount; i++)
{
map1[i] = map1.size();
}
for (auto value : map1)
{
cout << "key: " << value.first << " value: " << value.second << endl;
}
return 0;
}
The result in Visual Studio :
key: 0 value: 0
key: 1 value: 1
The result in linux compiled with g++ -std=c++11 -Wall -pedantic
key: 0 value: 1
key: 1 value: 2
I have two questions:
As far as I understand c++, the VS implementation is right.
If I change the code to:
for (int i=0; i < keyCount; i++)
{
unsigned int mapSize= map1.size();
map1[i] = mapSize;
}
then it behaves like Visual Studio on both platforms.
Shouldn't the code always behave like this?
2.What Visual Studio compiler settings can I use to make sure that VS will compile the same as Linux?
I am working on Windows, but have an assignment that must work on Linux.
map1[i] = map1.size();
expands to
(map1.operator[](i)) = (map1.size());
C++ makes no guarantees about whether operator[] or size is called first, since both are operands to the assignment expression. Both compilers are correct.
You should split your expression into two statements if you expect one behavior or the other.
Consider the following code:
#include <sstream>
#include <iostream>
int main()
{
std::stringstream ss;
//auto loc = std::locale("de-DE"); // A
auto loc = std::locale(""); // B
ss.imbue(loc);
ss << 1.01;
std::cout << "standard formatting: " << 1.01 << std::endl;
std::cout << "localized formatting: " << ss.str() << std::endl;
}
Now, this works as expected or it freezes in line B. When using line A it is the same but I think that changing from A to B or vice versa leads to a higher chance that it works. It even happened that it worked one time and starting it again it freezes in line A or B respectively.
It is important that all this happens only when I start debugging from within VS 2015. When I execute this program from console it never freezes (release or debug doesn't matter).
So is this a Visual Studio bug?