Segmentation fault on list in C++ [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm using a class which holds a private list:
class Set
{
private:
list<long long unsigned> ways; //holds tags of addresses
and as part of the class's functionality I'm managing a LIFO on the list 'ways':
list<long long unsigned>::iterator it = ways.begin();
while (it!= ways.end()) //looks for the tag in the list
{
if ((*it) == tag) //tag is found in this set. moves the tag to the end of the list
{
ways.erase(it);
ways.push_back(tag);
return true;
}
it++;
}
return false;
and:
if (occupied < maxWays) //if the set is not all used up just pushes tag in the end
{
ways.push_back(tag);
occupied++;
return false;
}
else // if used up pops the front member (the least recently used one)
{
ways.pop_front();
ways.push_back(tag);
}
return true;
Nothing else touches 'ways' and nothing else erases the class 'set'.
Multiple instances of the class 'set' are created at the beginning.
During operation I'm getting Segmentation Fault for
list<long long unsigned>::iterator it = ways.begin();
which occurs after a long run. Trying to print the address of 'ways' before this line shows that at the point that I'm about to get Segmentation Fault the address of 'ways' changed dramatically.
All the previous times it was around 0x6000xxxxx for each instance, and at that time it was 0x23.
I don't have a clue what can cause that, please assist.

It might be that you delete an element from the list, and then increment the iterator, which points to the deleted element.
You probably need to forward the iterator first, and then remove the previous, to achieve what you want.
See:
Can you remove elements from a std::list while iterating through it?
EDIT: See also the return value of erase(), and similar operations that modify the iterator bag.
http://www.cplusplus.com/reference/list/list/erase/

Are you initiliazing 'occupied' and 'maxWays' ? If not, see example where it fails as we are calling ways.pop_front() on empty list ways
class Set
{
public:
Set(int max)
{
maxWays = max;
occupied = 10; // Say randomly stored value 10 is more than maxWays = 5
}
bool search(long long tag)
{
list<long long unsigned>::iterator it = ways.begin();
while (it!= ways.end()) {
if ((*it) == tag) {
ways.erase(it);
ways.push_back(tag);
return true;
}
it++;
}
return false;
}
bool add(long long tag)
{
if (occupied < maxWays) {
ways.push_back(tag);
occupied++;
return false;
}
else {
ways.pop_front(); // may fail here
ways.push_back(tag);
}
return true;
}
private:
list<long long unsigned> ways;
int maxWays;
int occupied;
};
int main()
{
Set set(5);
cout << set.add(100) << endl;
return 0;
}

Related

What's the difference b/w map[key] vs map.count(key) ? (particularly in this code) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 months ago.
Improve this question
So I was Solving a leetcode Problem and one dumb mistake made in debugg for more than an hour.
Leetcode Question
Answers(both working and not working)
Working code:
`
class Solution {
public:
int longestPalindrome(vector<string>& words) {
unordered_map<string,int> map;
for(string s:words){
map[s]++;
}
bool isOdd = false;
int ans = 0;
for(auto i:map){
string rv = i.first;
reverse(rv.begin(),rv.end());
if(i.first[0]==i.first[1]){
if(i.second%2==0)
ans+=i.second;
else{
ans+= i.second-1;
isOdd = true;
}
}
else if(i.first[0]<i.first[1] && map.count(rv)){
ans += 2*min(i.second,map[rv]);
}
}
if(isOdd){
ans++;
}
return 2*ans;
}
};
Not working code:
`
class Solution {
public:
int longestPalindrome(vector<string>& words) {
unordered_map<string,int> map;
for(string s:words){
map[s]++;
}
bool isOdd = false;
int ans = 0;
for(auto i:map){
string rv = i.first;
reverse(rv.begin(),rv.end());
if(i.first[0]==i.first[1]){
if(i.second%2==0)
ans+=i.second;
else{
ans+= i.second-1;
isOdd = true;
}
}
else if(i.first[0]<i.first[1] && map[rv]){
ans += 2*min(i.second,map[rv]);
}
}
if(isOdd){
ans++;
}
return 2*ans;
}
};
The only difference between both code is map[rv] ==> map.count(rv)
test case which is giving error:
["oo","vv","uu","gg","pp","ff","ss","yy","vv","cc","rr","ig","jj","uu","ig","gb","zz","xx","ff","bb","ii","dd","ii",
"ee","mm","qq","ig","ww","ss","tt","vv","oo","ww","ss","bi","ff","gg","bi","jj","ee","gb",
"qq","bg","nn","vv","oo","bb","pp","ww","qq","mm","ee","tt","hh","ss","tt","ee","gi","ig","uu","ff","zz",
"ii","ff","ss","gi","yy","gb","mm","pp","uu","kk","jj","ee"]
Can anyone please help me?
I've tried googling this stuff but couldn't find it. then i've tried asking few people on discord. but no progress.
I just wanna know why above(not working part) code in not working.
What is the deal with map[key] and map.count(key)?
When should i use which one?
std::map.count() will check, if an element with a given key exists. It will not modify the container. Please see here. It is even defined as constto indicate that fact.
The std::maps index operator is different. It
returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
So, if the key does not exist, it will add an entry to the map, with this new key.
Therefore your second code cannot work.
map[rv] isn't a regular getter. It inserts default element if key is not found.
so you mutate (unordered_map) map whereas you iterate on it (which (might) invalidate iterator, making you loop undefined behavior).

Parenthesis Checker gfgs [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
The following code is giving segmentation fault can anyone tell why. this is a geeks for geeks practice problem (Parenthesis Checker) .
Q- Given an expression string x. Examine whether the pairs and the orders of “{“,”}”,”(“,”)”,”[“,”]” are correct in exp.
For example, the function should return 'true' for exp = “[()]{}{()()}” and 'false' for exp = “[(])”.
bool check(string s)
{
stack<char> save;
int x = s.size();
for(int i=0;i<x;i++)
{
if(s[i]=='{' || s[i]=='['|| s[i]=='(')
{
save.push(s[i]);
}
else if(s[i]=='}'){
if(save.top()=='{')
{
save.pop();
}
else{
return false;
}
}
else if(s[i]==']')
{
if(save.top()=='[')
{
save.pop();
}
else{
return false;
}
}
else if(s[i]==')')
{
if(save.top()=='(')
{
save.pop();
}
else{
return false;
}
}
}
if(!save.empty())
{
return false;
}
else{
return true;
}
}
You have a chance to seg-fault when the stack is empty and the next character in the string is a closing paren.
E.g. if the input string is ")" or "())" your program will not behave as intended.
You will need to change the if statements from
if (save.top() == '('){...} to if (!save.empty() && save.top() == '('){...}
And similarly for every other case where you check save.top (The preceeding code does not guarantee that the stack is not empty at that given point).
Note: You would also need to do this for each occurrence of pop as well, but the guards before top() will guarantee that the stack is not empty when you then pop.

STL map find doesn't work properly [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm having a map containing 1323 records, which is getting filled the following way:
std::map<uint32_t, House*> m_houses;
[...]
void OnReceiveHousePacket(HouseTable_t* recvTable, int32_t size) {
m_houses.clear();
for (int32_t i = 0; i < size; ++i, ++recvTable) {
House* h = new House;
memcpy(&h->table, recvTable, sizeof (HouseTable_t));
m_houses.insert(std::make_pair(recvTable->clientId, h));
}
}
The issue I'm having with this, is that when I am trying to find a record by key:
const House* Get(uint32_t clientId) {
auto it = m_houses.find(clientId);
if (it == m_houses.end()) {
return nullptr;
}
return it->second;
}
It returns nullptr, although the key exists and I am sure about that.
m_houses.count(clientId) returns 0 as well
However, when I change the Get([...]) function contents to the following loop, everything works like a charm without any issues which proves that the record really exists in the map:
for (const auto& h : m_houses) {
if (h.first == clientId) {
return h.second;
}
}
return nullptr;
It's the first time I am having an issue like that with STL's map.
What is the problem? I've always been using this way to find a record and never faced such issue.
edit
HouseTable_t and House:
struct HouseTable_t {
char name[24 + 1];
char owner[64 + 1];
int clientId;
int type;
int rank;
unsigned char identifier;
}
class House{
public:
House() = default;
HouseTable_t m_table;
int id;
int data;
};
This:
memcpy(&h, ...
Should be:
memcpy(h, ...
Otherwise you're trashing the pointer.

Set function in c++ not working [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Im writing a Set class in c++(i know there is already a library this is an assignment) and similar to the one in C++ im writing a function to check if the entry being inputted is already in the set
void Set::insert(const Set::value_type& entry)
{
for (int i=0; i<used;i++)
{
if(data[i]!=entry && used<CAPACITY)
{
data[used] = entry;
used++;
}
else
{
throw "Out of capacity in Set and Intger already in Set";
}
}
}
What the function does is look if the number is in the set. If the number is not in the set and if used < capacity (meaning their is still room) then the number is inserted. When i use the insert function nothing happens. Could someone help me out. Maybe im approaching this the wrong way.
As written, when insert-ing to an empty Set, used will be 0, so the loop terminates without doing anything. You don't handle the case where the value wasn't found after the loop, so it never inserts.
Even if you switched to loop to CAPACITY, the inner check is going to fill the whole Set with the same value on first run (because the if check's block executes, but doesn't break the loop, so it stores the same value over and over until it fills the Set or finds itself), then on subsequent inserts, it will immediately raise an exception for being full. Perhaps you wanted something like this?
void Set::insert(const Set::value_type& entry)
{
// If you have a membership test function, you can reuse it here instead
// of including this loop, e.g.:
// if (this->contains(entry)) return;
for (int i=0; i < used;i++)
{
if (data[i] == entry) {
// value already in set, nothing to do
return;
}
}
// Not already in Set, add if we have room or raise exception
if (used < CAPACITY) {
data[used++] = entry;
return;
}
throw "Out of capacity in Set";
}
When the set is initially empty, so that used == 0, your loop doesn't do anything, because the i < used condition fails immediately. So you never add the new item to the set.
And if there are items in the set, the loop adds the new entry to the set if it's different from any existing element. It adds it repeatedly for each element that it's not equal to.
What you need to do is go through the entire set, and see if a match is found anywhere. If it makes it through the entire loop without finding a match, it adds the new entry.
void Set::insert(const Set::value_type& entry)
{
for (int i=0; i<used;i++)
{
if(data[i] ==entry)
{
return;
}
}
// Not found, add it
if (used < CAPACITY) {
data[used++] = entry;
} else
{
throw "Out of capacity in Set";
}
}

Trouble removing elements from C++ vector

I'm trying to remove 'dead' bullets from my vector of bullets. Every frame, I'm calling the Bullet::update() function which looks like this:
void Bullet::update()
{
for(int i = 0; i != mAmmo.size(); i++)
{
if(mAmmo[i].sprite.getPosition().x > 700)
mAmmo[i].mAlive = false;
if(mAmmo[i].mAlive == false)
{
// I get a Debug Assertion Failed at runtime from this piece of code
mAmmo.erase(mAmmo.begin()+i);
}
if(mAmmo[i].mAlive == true)
{
mAmmo[i].sprite.move(mMovement);
}
}
}
Am I doing this completely incorrectly? This is the first time I've really used vectors more than just following through a tutorial. If I need to post any more code, just tell me. I've been working on this for the past few hours, so I'm a wee bit desperate to get this to work.
Thanks in advance!
You're easily walking into undefined behavior as soon as the ith element is the last element in your list. Use iterators, and pay special attention to the return value of erase(), as it automatically advances the iterator for you so your loop doesn't have to.
void Bullet::update()
{
for (auto it = mAmmo.begin(); it != mAmmo.end();)
{
if(it->sprite.getPosition().x > 700)
it->mAlive = false;
if (!it->mAlive)
{
// erase and get next iterator
it = mAmmo.erase(it);
}
else
{ // move and increment
it->sprite.move(mMovement);
++it;
}
}
}