This question already has answers here:
segmentation fault when trying to cin into a string?
(3 answers)
How to use a C++ string in a structure when malloc()-ing the same structure?
(5 answers)
Closed 3 years ago.
I want to copy the values of one struct to another which has the same template.
Below is the sample code, where struct list is the template structure. Calling func1() must copy the contents of li to ref.
But when copy is performed segmentation fault occurs. Where I am going wrong with it ?
foo.cpp
#include<iostream>
#include <cstdlib>
class bar
{
public:
void func1(const list& li);
};
void bar::func1(const list& li)
{
listref ref = nullptr;
ref = (listref)malloc(sizeof(listref));
ref->a = li.a;//segfault occurs here
ref->b = li.b;
ref->c = li.c;
ref->d = li.d;
}
foo.h
#include<iostream>
struct list
{
std::string a;
int b;
int c;
const char* d;
};
typedef struct list* listref;
main.cpp
#include <iostream>
#include "foo.h"
#include "foo.cpp"
int main()
{
list l1;
std::string temp = "alpha";
l1.a = "alphabet";
l1.b = 60;
l1.c = 43;
l1.d = temp.c_str();
bar b;
b.func1(l1);
return 0;
}
You are mixing C and C++ concepts and this is what happens!
Your class list contains a member of the C++ type std::string, a complex class with semantics that you need to uphold.
Then you do a malloc over it!
Even if your size argument to malloc were correct (which it isn't; you merely gave it the size of a pointer), this does not properly construct anything. It should be new or std::make_unique!
Do not mix C and C++ idioms.
Related
This question already has answers here:
Why does the C++ map type argument require an empty constructor when using []?
(6 answers)
Closed 5 years ago.
I've done a lot of Googling and can't seem to figure out what's going on. I'm teaching myself C++ (I'm more familiar with Java).
I have Item Class objects that are being stored in an Inventory Class map, not as pointers. I want to retrieve one of the items from the Inventory in a function, assign it to a temp variable while I delete it from the Inventory map, and then return the object itself so something else can use it. When I originally tried using the code within my function it was returning the error (followed by the stack trace of c++ library stuff):
no matching constructor for initialization of 'Item'
::new ((void*)__p) _Tp();
I tried creating a copy constructor, but to no avail. Eventually, it worked by including an empty constructor ( Item(); ) in my header file and defining it in my cpp file ( Item::Item() {} ).
I would just like to understand why this was necessary so I can recognize it in the future to know what I'm doing.
EDIT: Upon further inspection of the error stack trace, it turned out the actual problem with with the Inventory::addItem function. When assigning an object to a map using operator[], the map first instantiates the value type to the key using the default constructor before making the assignment. No default constructor was available, so the error was returned.
It was fixed by changing the line to map.insert({key, value})
Here are the important parts of the two class files:
//item.h
#include <string>
using namespace std;
class Item {
private:
string name;
int type;
int levelReq;
public:
Item(string name, int type, int levelReq);
Item();
string getName() {return name;}
int getType() {return type;}
friend ostream &operator<<(ostream &out, const Item &item);
};
---------------------------------------------------------------
//item.cpp
#include <string>
#include "item.h"
using namespace std;
Item::Item(string n, int t, int l) : name(n), type(t), levelReq(l) {}
Item::Item() {}
ostream &operator<<(ostream &out, const Item &item) {
return out << item.name;
}
---------------------------------------------------------------
//inventory.h
#include <map>
#include "item.h"
class Inventory {
private:
map <int, Item> inventory;
int size;
bool full;
int nextFree;
void findNextFree();
public:
Inventory();
bool isFull() {return full;}
void addItem(Item item);
Item getItem(int slot);
void showInv();
};
---------------------------------------------------------------
//inventory.cpp
#include <iostream>
#include <string>
#include "inventory.h"
#include "item.h"
using namespace std;
Inventory::Inventory() {
full = false;
nextFree = 1;
size = 28;
}
void Inventory::addItem(Item item) {
if (!full) {
inventory[nextFree] = item;
findNextFree();
}
else {
cout << "Your inventory is full (Inv::addItem)";
}
}
Item Inventory::getItem(int slot) {
Item item = inventory.at(slot);
inventory.erase(slot);
full = false;
if (nextFree > slot) {
nextFree = slot;
}
return item;
}
void Inventory::findNextFree() {
nextFree++;
if (nextFree == size + 1) {
full = true;
}
else if (inventory.count(nextFree)) {
findNextFree();
}
}
I think the issue rose because you declared a constructor for your item class.
C++ will automatically generate the necessary constructors if you don't provide any custom constructors.
The necessary constructors are the default, copy and move constructors.
The moment you provide one, the default constructors won't be generated and you have this issue. This principle will also apply to structs.
Check the reference to see for yourself:
http://en.cppreference.com/w/cpp/language/default_constructor
http://en.cppreference.com/w/cpp/language/copy_constructor
http://en.cppreference.com/w/cpp/language/move_constructor
Hope this answers your question.
This question already has answers here:
How to copy a char array in C?
(14 answers)
Assign array to array
(6 answers)
Closed 6 years ago.
I have this following code:
#include "stdafx.h"
#include<iostream>
using namespace std;
const int x = 5;
bool graf_adj[x][x] = {
0,1,1,1,0,
1,0,1,0,0,
1,1,0,1,1,
1,0,1,0,0,
0,0,1,0,0
};
struct Graf
{
bool adj[x][x];
char n;
};
int main(){
Graf graf1;
graf1.adj = graf_adj;
}
in main function when i try to assing graf_adj to graf1.adj
graf1.adj = graf_adj;
complier gives me this error:
Error Expression must be a modifiable lvalue
Can anybody give a solution to this ?
Thank you
Now that you have added the type for the const:
Here is the solution using memcpy
#include<iostream>
#include <cstring>
const int x = 5;
bool graf_adj[x][x] = {
0,1,1,1,0,
1,0,1,0,0,
1,1,0,1,1,
1,0,1,0,0,
0,0,1,0,0
};
struct Graf
{
bool adj[x][x];
char n;
};
int main(){
Graf graf1;
std::memcpy(&graf1.adj, &graf_adj, sizeof(graf1.adj));
}
This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 8 years ago.
I know this is a common error so I tried to create a minimal example. I think this is because I try to free stack memory but I don't quite understand how I could do differently.
Maze.h
#pragma once
class Maze
{
public:
Maze();
Maze(unsigned int height, unsigned int width);
~Maze();
private:
unsigned int m_height;
unsigned int m_width;
char *entrance;
char *exit;
char *m_cells;
};
Maze.cpp
#include "Maze.h"
using namespace std;
Maze::Maze()
{
}
Maze::Maze(unsigned int height, unsigned int width) :
m_height(height),
m_width(width)
{
m_cells = new char[m_height * m_width];
entrance = nullptr;
exit = nullptr;
}
Maze::~Maze()
{
delete entrance;
delete exit;
delete[] m_cells; //this line causes the error
}
main.cpp that causes an error
#include <iostream>
#include <string>
#include "Maze.h"
using namespace std;
int __cdecl main(int argc, char **argv)
{
Maze maze;
maze = Maze(10, 10);
}
main.cpp without error
#include <iostream>
#include <string>
#include "Maze.h"
using namespace std;
int __cdecl main(int argc, char **argv)
{
Maze maze(10, 10);
}
What are the differences between the 2 mains ? why does the first one cause an error ? This is a problem because I want to declare maze but to initialize it later in my program. Here I only do it in two lines to create a minimal example.
The error occurs when the program closes so I think it's a memory deallocation problem. Indeed, when I remove
delete[] m_cells;
from the destructor, no error anymore.
What's happening exactly here ?
The line:
maze = Maze(10, 10);
Is creating a copy of the object, so what happens is:
Maze(10, 10) - constructs a new object, who allocates memory with operator new and operator new[].
maze is assigned a copy of the object made in 1. This is done by simply assigning the pointer values of the first to the 2nd.
Then the object from 1 is destructed, it deletes the pointers.
maze eventually goes out of scope, it deletes the pointers again, here you crash.
To solve this read about the rule of 3, you need to add a copy constructor and an assignment operator.
For example:
// This the copy constructor
Maze::Maze(const Maze& other)
{
// Call the assignment operator, saves duplicating the assignment operator code in here.
*this = other;
}
// This is the assignment operator
Maze& Maze::operator = ( const Maze& other )
{
if ( this != &other )
{
// TODO: Copy your pointers, not by assigning them, but use operator new and copy the data as "other" will destruct and delete those pointers, hence your problem
}
return *this;
}
If you are using C++11 you could also use move construction/assignment too, then you would simply swap the pointers, and set the source objects pointers to NULL/nullptr.
In C++11 you can also use the default and delete keyword to prevent use of constructors you have no implemented that shouldn't be called, for example:
class Foo
{
public:
Foo() = default;
// Prevent copying
Foo(const Foo&) = delete;
Foo& operator = ( const Foo& ) = delete;
int x = 0;
};
This would cause the following to fail at the compilation stage:
Foo a;
a = Foo();
I'm new in C++ and I have something to do with a linked list, and I don't know why it doesn't work, need help from a prof :O)
Here's my .h
#ifndef UnCube_H
#define UnCube_H
using namespace std;
class ACube{
public:
ACube();
struct Thecube;
private:
void PrintList();
};
#endif
My ACube.cpp
#include <iostream>
#include "ACube.h"
ACube::ACube(){
};
struct Thecube{
int base;
int cube;
Thecube * next ;
};
void ACube::PrintList(){
};
and finally my main.cpp
#include <cstdlib>
#include <iostream>
#include "ACube.h"
using namespace std;
int main()
{
ACube * temp;
temp = (ACube*)malloc(sizeof(ACube));
for (int inc=1; inc <=20 ; inc++){
temp->ACube->nombrebase = inc;
temp->cube = inc*inc*inc;
}
system("PAUSE");
return EXIT_SUCCESS;
}
Everything was working fine, but when I add these lines :
temp->ACube->nombrebase = inc;
temp->cube = inc*inc*inc;
I add error saying :
'class ACube' has no member named 'TheCube'
'class ACube' has no member named 'cube'
Can someone help me because I want to create my list and fill the cube with number.
Other thing I want to use THIS. in the print,
Maybe someone can teach me what's wrong and how to do it !
Thanks for any help
You don't need to have a struct inside your class.
#ifndef UnCube_H
#define UnCube_H
using namespace std;
class ACube{
public:
ACube();
int base;
int cube;
ACube * next ;
private:
void PrintList();
};
#endif
ACube.cpp
#include <iostream>
#include "ACube.h"
ACube::ACube(){
};
void ACube::PrintList(){
};
Also, this string is wrong:
temp->ACube->nombrebase = inc;
it should be just:
temp->base = inc;
Last but not least, this code doesn't create a linked list, because you don't do anything with the ACube::next pointer.
There are so many horrible problems in your code, I suggest you should learn more C++ knowledge before writing linked list.
1. What is nombrebase?
I think nobody can answer.
2. You must allocate C++ class by new key word instead of malloc.
new invokes not only allocation but also class constructor, while malloc allocates only.
3. Thecube should been defined inside ACube
Since the code in your main() refers the member cube in class Thecube, main() must know what it is.
4. The member next in class ACube is a pointer which points to what?
What does a pointer point to without initilization? You should initial it in constructor, and destroy it in destructor.
5. temp->ACube
ACube is a class type, you can access member object, but not a type.
6. Never using namespace into a header file
It would make the client of header file has name collision.
The following is the corrected code. Just no compile error and runtime error, but this is NOT linked list:
ACube.h
#ifndef UnCube_H
#define UnCube_H
class ACube{
public:
struct Thecube
{
int base;
int cube;
Thecube * next;
};
ACube();
~ACube();
Thecube *next;
private:
void PrintList();
};
#endif
ACube.cpp
ACube::ACube()
: next(new Thecube)
{
}
ACube::~ACube()
{
delete next;
}
void ACube::PrintList(){
}
main.cpp
#include <cstdlib>
#include <iostream>
#include "ACube.h"
using namespace std;
int main()
{
ACube * temp;
temp = new ACube;
for (int inc = 1; inc <= 20; inc++)
{
temp->next->base = inc; // <-- This is not linked list, you shall modify.
temp->next->cube = inc*inc*inc; // <-- This is not linked list, you shall modify.
}
system("PAUSE");
return EXIT_SUCCESS;
}
Can someone explain me why this C++ code it's behaving this way?
And .. how can i avoid this 'vector' problems in the future.
#include <iostream>
#include <vector>
using namespace std;
struct my_str {
int x;
my_str() {
x = 0;
}
void insert();
};
vector<my_str> p;
void my_str :: insert() {
p.push_back(my_str());
x = 123;
}
int main() {
p.push_back(my_str());
p[0].insert();
cerr << p[0].x;
return 0;
}
p.push_back(my_str()); in void my_str :: insert()
causes vector reallocation, this is invalid
x = 123;
BOOM! Heap corruption.
To avoid such problems in future do not edit vectors from objects they contain.
Or, if you have to, make sure you do not use object members after this.