Deleting an array element declared in struct c++ - c++

I want to delete the array elements declared under student struct. I have only included parts of the code to reduce confusion.Please find the code below for the two relevant cases:
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
struct student
{
char name[20];
int id;
};
struct teacher
{
char name[20];
int id;
};
int main()
{
case 1:
cout<<"\t\t\t*********enter record**********"<<endl;
student st[2];
for(int count=0; count<2;count++)
{
cout<<"\t\t\t\tenter student "<<count<<" name"<<endl;
cin>>st[count].name;
cout<<"\t\t\t\tenter student "<<count<<" id"<<endl;
cin>>st[count].id;
}
break;
case 5:
cout<<"\t\t\t*********delete record********"<<endl;
for(int count=0;count<10;count++)
{
delete st[count].name;
}
break;
}
As seen in case 5 I am trying to delete the elements within the array using delete st[count].name;
I want to delete the elements of name and id in the delete case. However using delete st[count].name gives me a [Warning] Deleting array . And when I run the program it gives me a Program Recieved a signal SIGTRAP, trace/breakpoint trap. I am a beginner in c++ please help how I can delete the elements stored in these array. Thanks

There are 2 main problems in your code.
cin>>st[count].name
You're filling the array with user input, but the array can only hold 20 elements (and the last one must be a null terminator), if user inputs text with more then 19 elements, your program will result in undefined behavior.
Later, you're using
delete st[count].name
You're using delete on an array that is allocated on the stack, which is undefined behavior again, you would only need to use delete if you alocate an object using operator new, also you should use delete[] instead of delete for arrays.
The easiest fix to your program is changing char name[20] to std::string, std::string will resize itself to adapt to the text that it's holding dynamicly, while also taking care of clearning memory after itself, so you don't have to worry about that, later on it also has many useful methods that you may find useful, you can read more about std::string.
https://en.cppreference.com/w/cpp/string/basic_string

Related

Why am I getting a Segmentation fault: 11 in my C++ program?

I am currently experiencing trouble with an Segmentation fault : 11 in my C++ Program which uses object-oriented concepts:
//
// main.cpp
// pointersInOOP
//
// Created by Jayant Raul Rao on 15/05/15.
// Copyright (c) 2015 Jayant Raul Rao. All rights reserved.
//
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
class Student
{
public:
char * name;
int semesterHours;
float gpa;
};
int main(int argc, const char * argv[]) {
cout<<"Beta Version of 1.0 Student constructor. \n";
cout<<"\n";
cout<<"\n";
//Declaring a student object and a pointer
Student s;
Student *pOnS = &s;
//take userInput
printf("Please name the student... : ");
cin>>pOnS->name;
printf("Okay, you called your Student %s. Please now input the gpa of the Student: ", pOnS->name);
cin>>pOnS->name;
printf("The gpa of %s is %f", pOnS->name, pOnS->gpa);
return 0;
}
And when I execute this code I actually give my input and that always ends in a Segmentation fault. This error I get if I execute in the Terminal. If I execute directly in Xcode I get directed to a file called istream where there is written at a line: Bad access 0x1. Therefore I am unable to execute my program. I have already found out what Segmentation fault means.
Something like literally Stack Overflow. But I am unable to really understand any bugfix.
I thank you in advance,
Jayant Raul Rao
This code is un tested, but the main point is that it would be easier if you use a String type for the student name. So if you change char *name to std::string name your code will work.
If you want to stick to using char then you have to do something like this.
#include <string>
...
//take userInput
printf("Please name the student... : ");
std::string name;
cin>>name;
pOnS->name = new char(name.size() + 1);
strncpy(pOnS->name, name.c_str(), name.size());
pOnS->name[name.size() + 1] = '\0';
P.S fix this:
printf("Okay, you called your Student %s. Please now input the gpa of the Student: ", pOnS->name.c_str()); <-- if using String type
cin>>pOnS->gpa; //<----
class Student
{
public:
char * name; //you are not allocating memory for this.
int semesterHours;
float gpa;
};
You could use a character array like char name[15] or std::string
Also you are not initializing gpa before printing it.
A segmentation fault indicates some sort of invalid memory access. In this case, you're declaring a pointer (char * name), but never initializing it. So it points to some arbitrary value, which may or may not be a valid memory address. Then you try to write through it: cin>>pOnS->name;. This is undefined behaviour, which is likely to result in one of the following:
If the pointer's value is not a valid writable memory address, then you'll get a crash right away; the error that you'll get depends on the OS, but the most common ones are "segmentation fault", "general protection fault", or "bus error".
If the pointer's value is a valid writable memory address, then you'll overwrite whatever happens to be there. This may seem to work correctly, only for it to crash unpredictably when you try to run your program on a different computer, or at a different time. Or it may corrupt something that your program will try to use later, resulting in a crash in unrelated code.
To avoid this problem, ensure that you always write to valid memory locations. The easiest way to do that in this case is to use std::string rather than a raw character array.
Also, I think that your second write to pOnS->name should actually be to pOnS->gpa.
pons = new student;
Use the above statement after declaring pons as an object reference in the function. Rest looks fine and it worked for me hope it does for you too.

Simple Address Book using dynamic array

I am working on my school project related to "keeping contacts of customers" in C++.
I already finished my project using std::vector to store contact information for every added person. But now i have to write the same thing using DYNAMIC ARRAY.
Does anybody have any idea or sample code how to declare dynamic array with ability to change its dimension according to how many contacts are added by user ?
I need following:
* Declaration of dynamic array with undefined number of persons and with 6 contacts per each.
* Add a new contact.
* List all contacts in array.
I finished my project using vectors without any problems, but right now i am lost. I studied a lot of articles about working with dynamic arrays in c++ but with no progress. I was searching all around the internet for a sample piece of code that does what i need but can't find anything.
Although this is not exactly the same as your project, this was mine from a few days ago and we had to use a 2d dynamic array using the "new" and "delete" method for strings of names. Remember that any time you use "new" you need to have a "delete" otherwise you will get memory leaks. I hope this helps.
#include <iostream>
using namespace std;
#include <memory.h>
#include <string.h>
#include "ReadString.h"
#include "sort.h"
void main ()
{
bool contMain=true;
const long numNames=20;
long nameAc=0;
char ** ppNames;
ppNames=new char* [numNames];
char test;
while(contMain && nameAc<numNames)
{
ppNames[nameAc]=ReadString();
test=ppNames[nameAc][0];
if(test=='\0')
{
contMain=false;
}
nameAc++;
}
cout<<"Your names unsorted are:"<<endl;
print(ppNames, nameAc);
ppNames=sort(ppNames, nameAc);
cout<<"Your names, sorted, are:"<<endl;
print(ppNames, nameAc);
// deallocation... this will delete pNames and pTemp from the ReadString function
// as well as ppNames in main because they are all using the same pointers.
for(int i=0; i<nameAc; i++)
{
delete ppNames [i];
}
delete[] ppNames;
}
And here is the ReadString function.
#include <iostream>
#include <memory.h>
#include "ReadString.h"
using namespace std;
char * ReadString()
{
long aSize=10;
long numChars (0);
char * pNames;
char * pTemp;
char c;
pNames=new char [aSize+1];
while((c = cin.get()) != '\n')
{
if(numChars >= aSize)
{
aSize += numChars;
pTemp = new char[aSize + 1];
memcpy(pTemp, pNames, numChars);
delete[] pNames;
pNames = pTemp;
cout << "Array size increased to " << aSize << endl;
}
pNames[numChars++] = c;
}
pNames[numChars] = '\0'; //end of string
return pNames;
one thing you can easily use for this are linked lists. Your data structure has a pointer to the next list element.
struct ListElement
{
CustomerData cutomer;
ListElement *next;
}
You can add infrastructure for adding removing, finding, print-all etc. using such a datastructure as basis.
Another way is doing it really dynamic:
Example adding one item:
malloc memory for as many items as you already have + 1
copy the data from the old to the new memory
add the new item at the with +1 allocated space
You'll need infrastructure for adding at the beginning, at the end, delete one in the middle etc. going with this scheme. Allocate as much memory as you need after the change, copy the old data, insert/remove one item.
Good luck with your project!
The best that I can so is to suggest links to articles. It sounds like your instructor wants you to write the same program in "the hard way" using a more primitive set of tools. Since std::vector is essentially a dynamic array, I have to assume that he wants you to rewrite the project where you have to manually manage the memory. Here are some starting points. Remember, that google is your friend!
C++ FAQ Lite
Dynamic Memory Cplusplus.com
LMGTFY

c++ dynamic stuct pointer to char array

I'm having trouble dynamically assigning memory to a char array inside a pointer to a struct.
This is a homework assignment that has to use this struct outline:
struct Student
{
char *namePtr;
unsigned int score;
};
this is the part im having trouble with though
/***************************
* takes value from temporary value and puts into dynamic allocated Student array
***************************/
bool updateStructPtr(Student **info, unsigned int index, char *name, unsigned int score)
{
try
{
info[index]->namePtr = new char [strlen(name)+1];
if(DEBUG) cout << "size for dynamic char: " << strlen(name)+1 << endl << endl;
//copy char array into new array
strcpy(info[index]->namePtr, name);
info[index]->score = score;
}
catch (bad_alloc & param)
{
info[index]->namePtr = NULL;
return false;
}
return true;
}
my prof said:
A glance at your code reveals that you do not seem to be dynamically allocating memory for the Student structure as specified in the first sentence of step 3-2 of the algorithm I provided you.
3-2. Dynamically allocate memory for a Student structure. Place the address of this Student structure in the array of structure pointers. You will also need to dynamically allocate just enough memory to store the name. Do not store the quote characters. Populate the fields of the Student structure with the two items from Step 3-1.
The pointers in the pointer array point to random locations in memory and you are trying to use these random addresses. That could certainly explain why the program crashes. Actually there are many ways to crash this program and all steps must be followed carefully to avoid this.
but i have no idea how to fix this or where to begin.
SO isn't really intended for help with your homework.
That being said, the instructions from your teacher are quite elaborate and correct. You'll have to use new Student and new Student[] at one point or another to actually update the Student ** info that is passed to you in order to add that new Student struct you're supposed to add.
I'm guessing Student instances are not allocated before the function is called. You would have to allocate a new instance of Student via new Student and store it into info at index.
info[index] = new Student;

Segmentation fault in the code

Here, I am basically trying to input a string, break it into individual words and assign each word to a char pointer ptr[i].On executing the following code, if I input string of more than one word, it shows Segmentation fault (core dumped). I used gdb for debugging. But after I visit while loop 2nd time, it showed Program received signal SIGSEGV, Segmentation fault.
0x0000003b64a81321 in __strlen_sse2 () from /lib64/libc.so.6
The solution for it is to allocate memory to each ptr[i] before strcpy(ptr[i],cp); using ptr[i]=new char[sizeof(cp)];. But, how is it that no memory allocation needed for ptr[0]? If I don't allocate memory to ptr[0], are there any chances of something else being overwritten? I am asking it out of curiosity, I know its always better to allocate memory. Here is the code:
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int main()
{
int i,j;
string s1;
getline(cin,s1);
char s[100],*ptr[10];
strcpy(s,s1.c_str());
char *cp;
cout<<"string is: "<<s1<<endl;
cp=strtok(s," ");
i=0;
while(cp!=NULL)
{ cout<<cp<<endl;
strcpy(ptr[i],cp);
cp=strtok(NULL," ");
i++;
}
for(j=0;j<i;j++)
{ cout<<ptr[j]<<endl;
}
return 0;
}
When you declare a local variable, it's contents is undefined. So when you declare an array of pointers, the pointers in the array will be pointing to seemingly random locations. Using an uninitialized pointer is undefined behavior. Undefined behavior may lead to a crash, or it may seemingly work, but you can't say beforehand what will happen.
There are two solutions to your problem:
Allocate memory for ptr[i] (even when i is zero).
Assign the pointer cp to ptr[i] instead.
Splitting a string on space can be done much more simpler in C++ than what you have though, see for example the following simple program:
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
int main()
{
// Put a string into a string stream
std::istringstream is("hello world how are you today");
// Vector where to store the "words"
std::vector<std::string> words;
// Now split the string on space
std::copy(std::istream_iterator<std::string>(is),
std::istream_iterator<std::string>(),
std::back_inserter(words));
// And finally print the words
for (const auto& word : words)
std::cout << word << '\n';
}
The output from this is:
hello
world
how
are
you
today
Here's a list of references for the used functions/classes:
std::istringstream
std::vector
std::copy
std::istream_iterator
std::back_inserter
Segmentation Fault occurs when you try to access that part of memory that your program is no allowed to. When you do
char *p[10];
it defines an array of 10 pointers. The content of array is unknown. Hence it could be memory location outside your program's. Possibly the 0th index has some value that is part your program's address space and hence it didn't complain. 2nd index had something that is not part your address space.
So, the behaviour is undefined. It totally depends on the content of array
Sometimes we may get no segmentation fault while using ptr[0], but this may not be the case always. And it is always better to allocate memory to the pointer before assigning any values to the object to which it is pointing.
Actually segmentation fault occurs due to the line :
strcpy(ptr[i],cp);
If you allocate some memory to ptr[i] with either new or malloc and then copy it should not sump.

C++ Assignment, strcpy and strlen with character arrays n pointers

I am working on this assignment and have encountered a problem. At one point, I have to ask the user for two input commands to be used later and I want them put in a char array. I then want to put the input they have into char* but I end up with a Segmentation fault
Here is a small part of my code that shows where I'm having problems:
#include <iostream>
#include <cstring>
using namespace std;
int main(){
char firstAns[80];
char * command1[5];
int ansLen;
//Ask for command
cout << "Please enter your first command(incl. args) or quit: ";
cin >> firstAns;
ansLen = strlen(firstAns);
for(int i=0; i < ansLen; i++){
strcpy(command1[i], firstAns);
}
The program that I ran this from compiles just fine but I have narrowed the segmentation fault to this part of the program and could use some help as a novice programmer :)
You have an array of char* called command. But you haven't allocated any memory for the pointers in the array, or even set them to null. SO they're random values, pointing to random memory locations. Strcpy is then overwriting those random locations, causing a seg fault. You need to allocate memory for those pointers by command[i]=new char[80] on all 5 rows first.
char * command1[5];
This is an array of char*s. However, it is uninitialized - the values can be any value, and as such they point to random, meaningless places in memory.
You then later use the uninitialized command1[i] in strcpy(command1[i], firstAns);. Essentially, what you have done is taken a random place in memory and tried to copy firstAns to it. No wonder your program crashes!
Before using a pointer, you have to initialize it to some value. If you need storage in memory, use malloc() to return storage of the correct size (sizeof(datatype)*length +1 if it is a string) and remember to free() the pointer returned from it when you're done with it.
Read more: http://www.cplusplus.com/reference/cstdlib/malloc/
(Gabe Sechan's solution is also valid. new and malloc are the C++ and C ways of allocating memory)
Additional Problem is here:
ansLen = strlen(firstAns);
for(int i=0; i < ansLen; i++){
strcpy(command1[i], firstAns);
}
ansLen is the length of firstAns, it may be possible that it is longer than 5. In this case,
if you try to access command1[i], you are going to access memory that out of bounds, results in segfault.
Meanwhile, you are using unitialized command1 as pointed out by Patashu and Gabe.