std::unordered_map segmentation fault in constructor - c++

I've been getting a strange segmentation fault when allocating objects that have unordered_map as an atribute, the debug seems to point to it happening somewhere over at hashtable.h when allocating the map. Anyone know why this happens?
i reaches a value of 13222438 before the segmentation fault.
struct Graph{
unordered_map<int,Graph*> neighbor;
int something(){return (int)neighbor[0]++;///so it doesnt get optimized out
}
};
int main(){
std::list<Graph*> test;
for(long long i=0; i< 100000000.0d;i++ ){
test.push_back(new Graph());
}
std::cout<< "Done" <<std::endl;
return 0;
}

When I adjust your program to actually compile, and build it in 64-bit mode, it completes fine.
When I build it in 32-bit mode, it does with:
terminate called after throwing an instance of 'St9bad_alloc'
what(): std::bad_alloc
because it runs out of memory.

You are mostly running into system memory limitations.
On my system, sizeof(Graph) is 56. It will take about 5 GB of memory to create 100000000 of just the objects. Of course, there are other overheads associated with dynamic memory allocation and creating a list of pointers.
I am to able to run the program in my environment when creating 10000000 objects, 10 times less than the number you are using, but the crashes if I add another zero to the end of that number.

Related

Segmentation fault in below program

I was trying to solve very basic problem SPOJ CANDY
I am getting a segmentation fault when submitting the below solution.
But in Visual Studio its working fine.
I also declared variables by considering the size (sum as long long int)
because it can be large
1) Is it due to the fact that I am declaring the array inside the while loop;
should I declare that array outside of while loop so that for every test cases it uses that same array
2) Is every time loop runs(for every test cases) the new array is created, will it lead to garbage collection or compiler will automatically free the memory after every test cases (I know about dynamic memory allocation in that case we have to free memory explicitly ) can you tell me in which scope I
should declare the variables?
I got above doubts because segmentation fault is regarding memory access.
#include<iostream>
using namespace std;
int main(){
while(1){
int n;
int arr[10001];
cin>>n;
if(n==-1)
break;
long long int sum=0;
for(int i=0;i<n;i++){
int temp;
cin>>temp;
sum+=temp;
arr[i]=temp;
}
int mean=sum/n;
if((sum%n)!=0){
cout<<-1<<endl;
continue;
}
int count1=0;
for(int i=0;i<n;i++){
if(arr[i]>mean){
count1+=(arr[i]-mean);
}
}
cout<<count1<<endl;
}
}
Your problem is probably due to the stack allocation of int arr[10001]. This is most probably a 40kB allocation. Now, "allocation" is the wrong word, as it essentially just calculates the address of arr by doing something like int * arr = STACK_POINTER-40004.
Unfortunately, it is common to have the maximum stack size be 12 kB by default. This means that the operating system maps 12 kB into memory and sets STACK_POINTER to the top of that memory (assuming the stack grows downward).
So the net effect is that your arr pointer now points beyond the allocated stack -- into unallocated memory -- and the first access throws a segmentation fault. Normally you could fix this by upping the stack size with ulimit -s, but you do not have control over the judging platform used.
You have two options:
use a heap allocation instead int *arr = new int[10001]. This is not affected by the initial stack size. In a normal program you should take care to clean this up, but for a short program like this it is not necessary.
move the declaration of int arr[10001] to the top level. arr will point to a region known as the BSS section, which is initially zeroed. This is also not affected by the initial stack size.

why cpp allows to get a access to memory i haven't allocated?

In cpp one can use an array declaration as
typename array[size];
or
typename *array = new typename[size];
Where array is of length 'size' and elements are indexed from '0' to 'size -1'
Here my question is am I allowed to access the elements beyond the index >= size.
So I wrote this little code to check it
#include <iostream>
using namespace std;
int main()
{
//int *c; //for dynamic allocation
int n; //length of the array c
cin>>n; //getting the length
//c = new int[n]; //for dynamic allocation
int c[n]; //for static allocation
for(int i=0; i<n; i++) //getting the elements
cin>>c[i];
for(int i=0; i<n+10; i++) //showing the elements, I have add up 10
cout<<c[i]<<" "; //with size to access the memory I haven't
//allocated for
return 0;
}
And the result is like this
2
1 2
1 2 2686612 1970422009 7081064 4199040 2686592 0 1 1970387429 1971087432 2686700
Shouldn't the program crashed but gives garbage values. And for both the allocation methods it gives the same result. It makes more bugs which are hard to detect. Is it related with the environment or the compiler I am using or anything else?
I was using codeblocks IDE having TDM-GCC 4.8.1 compiler on windows 8.1
Thanks in advance.
This is called "undefined behavior" in the C++ standard.
Undefined behavior can mean any one of the following:
The program crashes
The program continues to run, but produces meaningless, garbage results
The program continues to run, and automatically copies the entire contents of your hard drive, and posts it on Facebook
The program continues to run, and automatically subscribes you to Publishers Clearinghouse Sweepstakes
The program continues to run, but your computer catches fire and explodes
The program continues to run, and makes your computer self-aware, which automatically links and networks with other self-aware networks, forming Skynet, and destroying the human race
Conclusion: do not run and access elements past the end of your arrays.
The c++ compilers don't enforce this as there is no specification to do so.
When you access an element of an array there is no boundary check done. c[i] just gets translated to c + i * sizeof(int) and that's it. If that area of memory is not initialize you'll get garbage, but you could be getting other useful information it all depends on what is there.
Please note that depending on the OS and the c++ runtime you're running you can get different results, for instance on a linux box you'll probably be getting a segmentation fault and the program will crash.

Segmentation fault while reading Memory in C++

I am just trying to get Value stored at a specific memory address using two C++ codes
Code which I using to write data to memory and get its address :
#include <iostream>
using namespace std;
int main()
{
int i = 10;
cout<<&i<<endl;
cin>>i; // This is just to make sure program doesn`t end
return 0;
}
I used cin>>i; just to make sure that it doesn't end.
After getting the address of int i, put in the following code :
#include <iostream>
using namespace std;
int main()
{
// This address changes everytime and I change it everytime
// This is just one temporary address
volatile int *x = (volatile int *)0x7ffef9246e74; // [1]
int y = *x;
cout<<y<<endl;
return 0;
}
[1] : I copied this line from this page.
Program #1 keeps running while I run Program #2
On running the second code, I am getting segmentation fault (core dumped). Any help?
Your model of how modern operating systems, compilers, etc. work is wrong. When you run the program the first time, the process gets assigned a memory space. Everything within this memory space, which is a virtual memory space, gets mapped to physical memory by the processor's MMU.
When the process finished, its memory space no longer exists. The next time you start the same program, it will run in another and independent memory space. It might be mapped to different physical memory addresses and even the virtual addresses are either not the same or they are cleared to make sure that no information is leaked from former processes.
This means that when you enter the address from the first program into the second, it has no meaning there. What is worse is that the memory address from the first run is not part of the virtual memory space of the second one when you run it, hence the CPU's MMU detects an illegal access to a memory location and you get a seg-fault.

Project runs on Windows 7 but not on Linux with Virtual Box

I'm having a problem with a C++ project I made on Windows 7 using code-blocks. There it compiles perfectly and executes the program as desired however when I tried opening it with Virtual Box using Linux Mint Cinnamon 17 the program compiles but throws a segmentation fault error at runtime (more specifically "segmentation fault process returned 139 0x8b". I gave the Virtual Machine 2 GB of RAM. and here is the code which causes the program to stop.
string Tabla::linea(contenedor& lista, int lis_s)
{ //contenedor is: vector < vector <string> >
ostringstream os;
os<<"|";
for(int i=0; i< lista.size();i++)
{ int espacios =maximos[i]-lista[i][lis_s].size();
if(lista[i][0]=="<")
{
os<<" "<<lista[i][lis_s]<<string(espacios,' ')<<" ";
}
if(lista[i][0]==">")
{
os<<" "<<string(espacios,' ')<<lista[i][lis_s]<<" ";
}
if(lista[i][0]=="=")
{
os<<" "<<string( espacios / 2,' ')<<
lista[i][lis_s]<<string(espacios / 2,' ')<<" ";
if(espacios%2==1)
os << " ";
}
os<<"|";
}
return os.str();
}
Thank you very much.
This is known as "undefined behaviour", its when your code does something its not supposed to do, like read or write an out of bound element from a vector, write to a buffer that cannot hold as much data as you are trying to write to it etc.
It may result on a variety of unpredictable consequences like segmentation fault, stack overflow, memory overwrite, and it may even complete its task without aparent incidents.
This particular piece of code can be invoking undefined behaviour in numerous situations:
If maximos.size() is smaller than lista.size() its undefined behaviour when calculating espacios.
If lista[i].size() is smaller than lis_s+1 it will invoke undefined behaviour on every place of your code that refers to lis_s.
If lista[i].size() is smaller than 1 its undefined behavior on line if(lista[i][0]=="=").
Basically you have to make sure every element from those vectors you want to access exist before acessing them. You can either do that by checking all the sizes or make sure you set up everything right when populating those vectors with information.

Can the cause of SIGSEGV be the low ram of the system?

My system ram is small, 1.5GB. I have a C++ programm that calls a specific method about 300 times. This method uses 2 maps (they are cleared every time) and I would like to know if it is possible in some of the calls of this method that the stack is overflowed and the program fails. If I put small data (so the method is called 30 times) the program runs fine. But now it raises SIGSEGV error. I am trying to fix this for about 3 days and no luck, every solution I tried failed.
I found some cause of the SIGSEGV below but nothing helped
What is SIGSEGV run time error in C++?
Ok, here is the code.
I have 2 instances, which contain some keywords-features and their scores
I want to get their eucleidian distance, which means I have to save all the keywords for each of the instances, then find the diffs for the keywords of the first one with those of the second and then find the diffs for the remaining of the second instance. What I want is while iterating the first map, to be able to delete elements from the second. The following method is called multiple times as we have two message collections, and every message from the first one is compared with every message from the second.
I have this code but it suddenly stops although I checked it is working for some seconds with multiple cout I put in some places
Note that this is for a university task so I cannot use boost and all those tricks. But I would like to know the way to bypass the problem I am into.
float KNNClassifier::distance(const Instance& inst1, const Instance& inst2) {
map<string,unsigned> feat1;
map<string,unsigned> feat2;
for (unsigned i=0; i<inst1.getNumberOfFeatures(); i++) {
feat1[inst1.getFeature(i)]=i;
}
for (unsigned i=0; i<inst2.getNumberOfFeatures(); i++) {
feat2[inst2.getFeature(i)]=i;
}
float dist=0;
map<string,unsigned>::iterator it;
for (it=feat1.begin(); it!=feat1.end(); it++) {
if (feat2.find(it->first)!=feat2.end()) {//if and only if it exists in inst2
dist+=pow( (double) inst1.getScore(it->second) - inst2.getScore(feat2[it->first]) , 2.0);
feat2.erase(it->first);
}
else {
dist+=pow( (double) inst1.getScore(it->second) , 2.0);
}
}
for (it=feat2.begin(); it!=feat2.end(); it++) {//for the remaining words
dist+=pow( (double) inst2.getScore(it->second) , 2.0);
}
feat1.clear(); feat2.clear(); //ka8arizoume ta map gia thn epomenh xrhsh
return sqrt(dist);
}
and I also tried this idea in order to not have to delete something but it suddenly stops too.
float KNNClassifier::distance(const Instance& inst1, const Instance& inst2) {
map<string,unsigned> feat1;
map<string,unsigned> feat2;
map<string,bool> exists;
for (unsigned i=0; i<inst1.getNumberOfFeatures(); i++) {
feat1[inst1.getFeature(i)]=i;
}
for (unsigned i=0; i<inst2.getNumberOfFeatures(); i++) {
feat2[inst2.getFeature(i)]=i;
exists[inst2.getFeature(i)]=false;
if (feat1.find(inst2.getFeature(i))!=feat1.end()) {
exists[inst2.getFeature(i)]=true;
}
}
float dist=0;
map<string,unsigned>::iterator it;
for (it=feat1.begin(); it!=feat1.end(); it++) {
if (feat2.find(it->first)!=feat2.end()) {
dist+=pow( (double) inst1.getScore(it->second) - inst2.getScore(feat2[it->first]) , 2.0);
}
else {
dist+=pow( (double) inst1.getScore(it->second) , 2.0);
}
}
for (it=feat2.begin(); it!=feat2.end(); it++) {
if(it->second==false){//if it is true, it means the diff was done in the previous iteration
dist+=pow( (double) inst2.getScore(it->second) , 2.0);
}
}
feat1.clear(); feat2.clear(); exists.clear();
return sqrt(dist);
}
If malloc fails and thus returns NULL it can indeed lead to a SIGSEGV assuming the program does not properly handle that failure. However, if memory was that low your system would more likely start killing processes using lots of memory (the actual logic is more complicated, google for "oom killer" if you are interested).
Chances are good that there's simply a bug in your program. A good way to figure this out is using a memory debugger such as valgrind to see if you access invalid memory locations.
One possible explanation is that your program accesses a dynamically-allocated object after freeing it. If the object is small enough, the memory allocator keeps the memory around for the next allocation, and the access after free is harmless. If the object is large, the memory allocator unmaps the pages used to hold the object, and the access after free causes a SIGSEGV.
It is virtually certain that regardless of the underlying mechanism by which the SIGSEGV occurs, there is a bug in the code somewhere that is a key part of the causal chain.
As mentioned above, the most probable cause is bad memory allocation or memory leak. Check for buffer overflows, or if you try to access a resource after you free it.
1.5GB isn't that small. You can do a lot in 1.5GB in general. For 300 iterations to use up 1.5GB (let's say 0.5GB is used by the OS kernel, etc), you need to use roughly 32MB per iteration. That is quite a lot of memory, so, my guess is that either your code is actually using A LOT of memory, or your code contains a leak of some sort. More likely the latter. I have worked on machines with less than 64KB, and my first PC had 8MB of ram, and that was considered A LOT at the time.
No, this code is unable to cause a segfault if the system runs out of memory. map allocation uses the new operator, which does not use the stack for allocation. It uses the heap, and will throw a bad_alloc exception if the memory is exhausted, aborting before an invalid memory access can happen:
$ cat crazyalloc.cc
int main(void)
{
while(1) {
new int[100000000];
}
return 0;
}
$ ./crazyalloc
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
The fact that an alternative implementation also crashes is a hint that the problem is not in this code.
The problem is on the Instance class instead. It's probably not lack of memory, it should be a buffer overflow, which can be confirmed with a debugger.