I have got class "student.cpp"
#include <iostream>
#include "student.h"
using namespace std;
void student::setMarks(int m1, int m2) {
mark1 = m1;
mark2 = m2;
};
void student::setName(char *n) {
name = n;
};
int student::calc_media(void){
return (mark1+mark2)/2;
};
void student::disp(void){
cout << "Student:" << name << " \n media:"<< calc_media() <<"\n";
};
student::student(){
mark1 = 0;
mark2 =0;
name = "";
};
Header file "student.h":
ifndef CLASY_STUDENT_H
#define CLASY_STUDENT_H
#endif //CLASY_STUDENT_H
class student{
char *name;
int mark1, mark2;
public:
void setName(char *n);
void setMarks(int m1, int m2);
void disp(void);
int calc_media(void);
student();
};
And "main.cpp":
#include <iostream>
#include "student.h"
using namespace std;
int main() {
student s;
char* n;
int m1, m2;
cout << "Enter name:";
cin>> n;
cout << "Enter marks of two subjects:";
cin>> m1;
cin>> m2;
s.setName(n);
s.setMarks(m1, m2);
s.disp();
return 0;
}
I am running this usign Clion and Cmake is :
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
set(SOURCE_FILES main.cpp student.cpp student.h student.cpp student.h)
But when I run, it asks for name, but when I type something then I have got a memory fragmentation error. Whats wrong?
And could someone by the way tell me if it looks okey for C++? I am trying to switch from java to c++.
char* n;
...
cin>> n;
n is a pointer, supposed to point at a particular piece of memory. But you never set it. So it has some undefined value, pointing who-knows-where into some memory that you end up trying to overwrite. Most likely memory you are not allowed to overwrite, causing a segfault.
Don't try to use char* if you don't yet know about manual memory management (and once you do, you'll understand why not to). Use std::string.
From a quick glance, you can pretty much replace char* everywhere with std::string (as long as you #include <string>).
Similar to what others are saying, your variable n is an uninitialized pointer. Pointers, as the name suggests, are just signposts to a particular location in memory - the tell the CPU "go to this memory location for variable x".
Say you have an integer variable var, which is declared like this:
int var;
That variable occupies memory and you can assign it a value like this:
var = 5;
You can also declare a pointer to an integer like this:
int * var_ptr;
Now assuming var_ptr points to a valid integer I can assign a value to it like this:
*var_ptr = 5;
This says "put the number 5 at the memory location pointed to by var". However if var_ptr has not been initialized then it will point to a random location in memory that may overwrite something important, or attempt to write to a protected memory address causing a protection fault (segfault). This is what is happening in your code.
To initialize var_ptr to point to the address of var, we can do this:
var_ptr = &var;
The ampersand is the "address of" operator - it says "don't get me the value of var but instead get me the address of the memory location where var is stored".
So, to prevent your problem, you must initialize n to some valid memory location where you are able to safely write some data.
There are a few ways to do this. As #Stefan points out you can declare n to be a character array:
char n[20];
As #BobTFish points out you need some way to make sure that your input doesn't exceed the size of your array (20 bytes in this case). The solution is std::cin.width(20).
As #BobTFish also mentions, you could also using a std::string, like this:
std::string n;
std:cin >> n;
The std::string object will automatically take care of memory allocation.
If you really must use a char *, you can either take the address of a char array (here I take the address of the first element of the array):
char n_array[20];
char *n = &n_array[0];
std::cin.width(20);
std::cin >> n;
You could also use dynamic memory allocation:
char *n = new char[20];
std::cin.width(20);
std::cin >> n;
delete n;
Notice that if you use dynamic memory allocation you must free the memory using delete when you are done otherwise there will be a memory leak. Local variables (like the array) are allocated on the stack and therefore are automatically freed when the function returns. For this reason, and the overhead of dynamic memory allocation, you would be insane to use it here.
Related
I need someone to solve the problem which is a question of dynamic memory allocation and
dynamic deallocation.
Here's a part of code to create database
include <iostream>
#include <string>
using namespace std;
struct subject {
string subname;
int score;
string grade;
float gpa;
};
struct student {
string stuname;
int stunum;
int subnum;
subject *sub;
float avegpa = 0;
};
int main(void){
int i = 0;
cout << "Put number of students : ";
cin >> i;
student* p = new student[i];
.
.
.
delete p->sub;
delete[] p;
return 0;
}
here's my desired result
Now, I have to enter the value of i first, but I hope I can automatically set
the value of i.
In order to try number 1, I pushed back value of i and increased i, but there was an
error. I don't know why.
This is the error message from number 2.
C++ crt detected that the application wrote to memory after end of heap buffer
delete p->sub;
You never initialised p[0].sub. Deleting (or even reading) an uninitialised pointer will result in undefined behaviour. You may delete only what you new.
P.S. Owning bare pointers are a bad idea. I recommend using std::vector to manage dynamic arrays.
EDIT: Im quite new to c++ and programming as a whole.
I'm supposed to make a program where i use stucts and and an array of structs.
Security council < > Member of Security council
My task was to use the concept of "UML aggregation" to create a program where I use structs and struct arrays. (I hope you understand what I'm trying to say)
Since a Member of a Security council is a part of a Security council, and not the other way around, the struct of Security council must have an array of its members.(bear with me)
//example
struct Member_sc{
char * name;
int age;
};
struct Security_council{
Member_sc members[10];
};
Now, I've created this program and everything works perfectly (according to my teacher), but now she told me create an exact copy, but instead of the "members" array I must use an array of pointers to the Member_sc structs. Since I havent completely figured out how pointers work, I have come across some problems.
I can post the code to the original program if needed, but it contains 4 files(main, header, and some function files) and it would be a pain to try and post it here.
here is the prototype (all in one file, for now)
#include <iostream>
using namespace std;
struct member_sc{
string name;
};
struct security_council{
member_sc *point;
security_council **search; // ignore this for now
int n;
security_council():n(0){}
};
void in_mem( member_sc &x){
getline(cin,x.name);
}
void out_mem(member_sc &x){
cout<<x.name<<endl;
}
void in_SC(security_council &q, member_sc &x){
int num; //number of members
cin>>num;
for(int i=0; i<num; ++i){
in_mem(x);
q.point[q.n]=x;
q.n++;
}
}
void out_SC(security_council &q,member_sc &x){
for(int i=0; i<q.n; ++i){
out_mem(q.point[i]);
}
}
int main(){
member_sc y;
security_council x;
in_mem(y); // works
out_mem(y); // works
in_SC(x,y); // crashes after i input the number of members i want
out_SC(x,y); //
system("pause");
return 0;
}
The program crashes after you input the number of members you want in your Security council.
Is my way of thinking right? or should I use dynamic memory allocation?
in addition to that (my teacher gave me an additional task) create a search function using pointers. i thought that pointer to pointer may be good for that, but im not sure.
Any help or advice would be greatly appreciated.
( i think ill figure out the search thingy once i figure out how pointers to structs work)
The first part of your issue is this:
cin >> num;
this reads only the digits that have been typed and stops at the newline. Then, in in_mem the call to getline immediately reads a newline. You need to do:
cin >> num;
cin.ignore();
this will drain the input stream of any remaining input, or catch up so to speak.
However your core problem is that you don't allocate any memory for "point" to point to.
A pointer is just a variable holding a value that happens to be the address (offset from 0) of a thing in memory. If you are going to the airport and write "Gate 23" on a post-it note, the post it note is a pointer and "Gate 23" is the value.
In your code, that variable is uninitialized and will either be 0, if you are lucky, or some random address in memory if you aren't so lucky.
To the airport analogy: you arrive at the airport and find that your post-it note has "pizza" written on it. Not helpful.
Your teacher has actually specified an "array of pointers". Break that down: pointer to what? member_sc, that's member_sc*. And now make it an array
member_sc* pointers[10];
NOTE: This is not good, modern C++ - in modern C++ you would use something called a smart pointer (std::unique_ptr) probably.
std::unique_ptr<member_sc[]> pointers(new member_sc[10]);
Now you have 10 pointers instead of just one, and all of them will need some allocation to point to. The easiest way to do this is with the new keyword and the copy constructor:
for (int i = 0; i < num; i++) {
in_mem(x);
pointers[q.n] = new member_sc(x); // make a clone of x
q.n++;
}
or in modern C++
for (int i = 0; i < num; i++) {
in_mem(x); // x is temporary for reading in
pointers[q.n] = std::make_unique<member_sc>(x);
q.n++;
}
However there is a limitation with this approach: you can only have upto 10 security council members. How do you work around this? Well, the modern C++ answer would be to use a std::vector
std::vector<member_sc> members;
// ditch n - vector tracks it for you.
// ...
for (int i = 0; i < num; ++i) {
in_mem(x);
q.members.push_back(x);
// q.n is replaced with q.members.size()
// which is tracked automatically for you
}
but I'm guessing your teacher wants you to actually understand pointers before you get to forget about them with modern luxuries.
We need to re-use the pointer stuff we've just used above and change "pointers" to an array of pointers.
Which means we're going to want a pointer to a set of pointer-to-member_sc.
member_sc** pointers;
We'll need to assign some memory for this to point to:
cin >> num;
cin.ignore();
if (num == 0) {
// do something
return;
}
pointers = new member_sc[num];
luckily, using a pointer to an array is as easy as using an array, the only major difference being that you lose the size-of-array information -- all you have is the address, not the dimensions.
for (int i = 0; i < num; i++) {
in_mem(x);
q.pointers[i] = new member_sc(x);
q.n++;
}
I'm deliberately not providing you with a complete working example because this is obviously for a class.
You never initialize the memory that the point member refers to, yet then in statement q.point[q.n]=x; you attempt to use it.
Basically, after you read in the number of members, and before the for loop where you read in the individual members, you need to allocate an array of an appropriate number of member_sc objects and store it in q.point. Don't forget to free this memory when done using it.
Once you do that, you can also remove the member_sc &x argument from both in_SC and out_SC, as that will become unnecessary.
Finally, some validation of your input seems to be in place. Consider what will happen if the user enters a negative number, and you attempt to use that directly to determine the size of memory to allocate.
Here's a simple example showing how to use a dynamically allocated array of structures:
#include <iostream>
#include <string>
struct member_sc {
std::string name;
};
void test_array(int count)
{
if (count <= 0) {
return; // Error
}
// Allocate an array of appropriate size
member_sc* members = new member_sc[count];
if (members == nullptr) {
return; // Error
}
// ... fill in the individual array elements
for(int i(0); i < count; ++i) {
// ... read from input stream
// I'll just generate some names to keep it simple
members[i].name = "User A";
members[i].name[5] += i; // Change the last character, so we have different names
}
// Now let's try printing out the members...
for(int i(0); i < count; ++i) {
std::cout << i << ": " << members[i].name << "\n";
}
delete[] members;
}
int main(int argc, char** argv)
{
for(int count(1); count <= 10; ++count) {
std::cout << "Test count=" << count << "\n";
test_array(count);
std::cout << "\n";
}
return 0;
}
Example on Coliru
Of course, there are many other issues with this style of code, but I believe that's beside the point of this question. For example:
Instead of using bare pointers, it would be more appropriate to use some kind of a smart pointer.
Instead of a simple array, use some kind of collection, such as a vector.
Since you are asked to use an array of pointers, do so: replace
Member_sc members[10];
with
Member_sc* members[10];
Then fill out that array using dynamic memory allocation. As a matter of good form, at the end of the program remember to release the dynamic memory you have used.
Was writing some code for an assignment to take integers as input and place them in an array to be printed.
I'm cleaning up all of my pointers as far as I can tell but I keep getting the runtime error:
1 [main] new 3444 cygwin_exception::open_stackdumpfile: Dumping stack trace to new.exe.stackdump
body of code:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int array[10];
int * p = array;
int *readNumbers()
{
int i=0;
for(i=0;i<10;i++)
{
string number;
int numb;
cout << "enter digit " << i << " of 10" << endl;
getline(cin, number);
istringstream (number) >> numb;
array[i]=numb;
}
return p;
delete p;
}
void printNumbers(int *numbers,int length)
{
int i;
for(i=0;i<length;i++)
{
cout << i << " " << *(numbers+i) << endl;
}
}
and the main calling code:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
extern int *readNumbers();
extern void printNumbers(int *,int);
int main()
{
int * q = readNumbers();
printNumbers(q,10);
delete q;
return 0;
}
So just looking for a solution to the stack dump...
Also I'm sure the method I used to apply the string number returned by cin to the values contained in array[10] is not what the question was looking for so any notes on that would be great.
Thanks
It is not a good practice to return a pointer to a memory allocated inside a function, in this case, you are not even allocating it inside a function, you have done it in a global space.
It is a good practice to activate all your warnings during the compile, even treat them as error when you are doing an assignment.
As a tip, you can allocate the memory in your main function and then pass the pointer to the readNumbers function.T This way it remains inside the same scope and it is easier to manage.
also, the same way you pass the lenght of the array to the printnumbers function you should pass it to the readnumbers one instead of hardcoding it.
Your delete are invalid, you can only delete something you've allocated with new.
The first one is harmless because it's after a return, so never executed (BTW you should look at compiler warnings).
The second one might produce your crash.
Also I'm sure the method I used to apply the string number returned by cin to the values contained in array[10] is not what the question was looking for so any notes on that would be great.
That's OK. What's dubious is spreading the size of the array everywhere, what happens if you want to change it ?
trying to get ‘sval’ to contain the string “$1” – “$500” for array indexes 0-499. in the following code, however itoa is giving me strange strings in the code below:
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
typedef struct data_t {
int ival;
char *sval;
} data_t;
void f1(data_t **d);
int main()
{
data_t *d;
d=static_cast<data_t*>(malloc(500)); //is this even needed?
d = new data_t[500];
f1(&d);
}
/* code for function f1 to fill in array begins */
void f1(data_t **d)
{
int i;
char str[5];
for (int i=0; i<500; i++)
{
(*d)[i].ival=i+1;
itoa (i,str,10);
(*d)[i].sval= str;
}
}
it also seems itoa has been depreciated, but that was what i got when i googled int to string
You don't need ltoa, cout should be just fine. Why do you need to keep the number and its string representation in the array? when you do cout << 10 you get "10" on the output, you don't need any conversions of your own
You, on the other hand, do ltoa without allocating any memory for the strings, which is not healthy as you have probably noticed. You use a local variable (the same, for all the 500 array members), which you try to access after you exit the function - a big no-no, its undefined behavior.
And:
d=static_cast<data_t*>(malloc(500)); //is this even needed?
d = new data_t[500];
No. Not only not needed - shouldn't be there at all! When in C++ - use new and delete, never malloc, that's a C function.
I am trying to make a c++ program with a class which holds integers on the "heap" and has only one method, pop() which returns the first item in the class and removes it. This is my code so far:
#include <iostream>
using namespace std;
class LinkList {
int *values; //pointer to integers stored in linklist
int number; // number of values stored in linklist
public:
LinkList(const int*, int); // Constructor (method declaration)
int pop(); // typically remove item from data structure (method declaration)
};
LinkList::LinkList(const int *v, int n){
number = n;
*values = *v;
int mypointer = 1;
while (mypointer<n) {
*(values+mypointer) = *(v+mypointer);
mypointer++;
}
}
int LinkList::pop() {
if (number>0) {
int returnme = *values; //get the first integer in the linklist
number--;
values++; //move values to next address
return returnme;
}
else {return -1;}
}
int main() {
int test[] = {1,2,3,4,5};
LinkList l1(test,5);
cout << l1.pop() << endl;
LinkList l2(test,5);
cout << l2.pop() << endl;
return 0;
}
The issue is that its failing at the line *values = *v, if i remove the 4th and 5th lines from the main method, I no longer get this issue, so its go to be a memory management thing.
What I want to do is to get values to point to a continuous bit of memory with integers in. I have tried to use arrays for this but keep just getting random memory addresses returned by pop()
Background: normal I programming in java, I've only be using C/C++ for 2 months, I'm using eclipse IDE in ubuntu, I can make very basic use of the debugger but currently I dont have functioning scroll bars in eclipse so I can't do somethings if they dont fit on my screen.
You are dereferencing an uninitialized pointer (values) at the line *values = *v; which is undefined behavior (UB). What this line says is "get the integer that values points to and assign to it the value pointed by v". The problem with this logic is that values doesn't yet point to anything. The result of this UB is the crash that you receive.
There are many other problems with this code, such as passing a const int* to the constructor with the intent of modifying those values. The biggest problem is that this is not an actual linked list.
*values = *v;
You dereference the values pointer in this line before initializing it. This is the source of the later errors, and the non-errors in the first three lines of main are simply due to luck. You have to allocate space via values = new int[n] and deallocate it in the destructor via delete[] values. std::vector does this work in a clean and exception-safe way for you.
Perhaps the problem is that you're incrementing an integer - mypointer, rather than a a pointer. If the integer requires more than one byte of space, then this might lead to errors. Could you try declaring a pointer and incrementing that instead?
The values member variable is a pointer to uninitialized memory. Before you start copying numbers into it you have to point it to valid memory. For example:
LinkList::LinkList(const int *v, int n){
number = n;
values = new int[n]; // allocate memory
int mypointer = 0;
while (mypointer<n) {
*(values+mypointer) = *(v+mypointer);
mypointer++;
}
}
LinkList::~LinkList() {
delete values; // release memory
}
Also, why do you call this a linked list while in fact you are using a memory array to store your numbers?