glibc detected : double free or corruption - c++

I will explain the brief coding steps I have done and area where I am facing the problem
main.cpp
int main()
{
int cnt_map,i=1,value;
/* My question is about this char pointer "key" */
char *key =(char*)malloc(sizeof(char) * 25);
if(key!=NULL)
{
printf("Key value is not NULL,its value is:%x\n",key) ;
cout<< "Enter the number of elements required in container map"<<endl;
cin >> cnt_map;
for (i=1;i<=cnt_map;i++)
{
cout << "Enter the key : ";
cin >>key;
cout << "Enter the key value:" ;
cin >>value;
printf("value pointed by ptr key: %s, value in ptr: %x\n", key,key);
c -> add_map1(key,value); //Function inserts value to map container
key+=sizeof(key);
}
c -> size_map1(); //Function displays size of map container
c -> display_map1(); //Function displays contents of map container
if(key)
{
printf("FINALLY:value pointed by ptr key: %s, value in ptr: %x,size:%d\n",key, key, sizeof(key));
free(key);
}
}
return 0;
}
when tried compiling and running the above code, I am able to successfully compile the code but got "glibc detected : double free or corruption" when tried running the application.
Now my question is I created a char pointer(char *key =(char*)malloc(sizeof(char) * 25);)
and successfully assigned memory to it using malloc. After completing my process when I tried freeing of that char pointer I am getting double free or corruption error. I learned that any variable assigned memory with malloc/calloc should be freed finally. Please tell why I am this getting error, why I should not do this? Please tell me how the memory operations are ongoing on char* key (if possible pictorially).
Note: The code presented above is not the complete code, I just explained where I am getting the problem and if I am not freeing the pointer variable, my application is running successfully.

By doing this:
key+=sizeof(key);
your key variable is no longer pointing to the start of the memory you allocated. You must pass the original pointer to free(). You need to store the original pointer in another variable so that you can correctly free() it at the end.
(You may be able to simply remove that line - I'm not sure what it's doing, given that sizeof(key) is either 4 or 8. I suspect it's redundant.)

That's because of this line : key+=sizeof(key); . key doen't contain the same address as the malloc returned address.
For example:
char *key =(char*)malloc(sizeof(char) * 25);
Let's say malloc returns the address 20000 (totally dumb address, it's just for the example).
Now you're doing key+=sizeof(key);, so key = 20000 + 4 = 20004. The problem is you're trying to free key, which points to the address 20004 instead of 20000.
In order to fix that, try this:
int main()
{
int cnt_map,i=1,value;
char *key_save;
/* My question is about this char pointer "key" */
char *key =(char*)malloc(sizeof(char) * 25);
key_save = key;
if(key!=NULL)
{
printf("Key value is not NULL,its value is:%x\n",key) ;
cout<< "Enter the number of elements required in container map"<<endl;
cin >> cnt_map;
for (i=1;i<=cnt_map;i++)
{
cout << "Enter the key : ";
cin >>key;
cout << "Enter the key value:" ;
cin >>value;
printf("value pointed by ptr key: %s, value in ptr: %x\n", key,key);
c -> add_map1(key,value); //Function inserts value to map container
key+=sizeof(key);
}
c -> size_map1(); //Function displays size of map container
c -> display_map1(); //Function displays contents of map container
if(key)
{
printf("FINALLY:value pointed by ptr key: %s, value in ptr: %x,size:%d\n",key, key, sizeof(key));
free(key_save);
}
}
return 0;
}

Simply remove the line:
key+=sizeof(key);
key is not a pointer to an array of strings, it's a pointer to a single string. Every time you increment this, you're reducing the available space in the string. The first time you read a key, there's 25 bytes available. The next time, you've incremented key by 4 or 8 bytes, but the end of the allocated space hasn't changed, so now there's only 21 or 17 bytes available. The third time it's only 17 or 9 bytes, and so on. After a few iterations, you'll increment key past the end of the memory block that you allocated, and it will start writing into unallocated memory (or memory that's assigned to other data structures). This is undefined behavior, and will most likely cause unpredictable failures in your program.
Since you're using C++, you should use std::string instead of char[] for strings, and std::vector instead of ordinary arrays. These data structures automatically expand as needed, so you avoid buffer overflows like this.

this is not taking your code into consideration, but i had a same problem in Reader writer problem (operating systems) http://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem.
It was due to file pointer being global so whenever any reader tried to read and in b/w another read reads and closes file pointer so when another reader which has not finished reading tried to close file pointer after reading. so what happened is file pointer was already closed it wasn't pointing to any file.
Solution i used.
Instead of declaring file pointer global i declared it local to reader function that it or else you can check file pointer for NULL and if NULL then don't close the file pointer.
#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#include<string.h>
#include<stdlib.h>
sem_t x,wsem;
int rc=0;
char ch;
char str[20];
void *reader(void *);
void *writer(void *);
int main()
{
int nw,nr,i=0,j=0;
pthread_t w[10],r[10];
sem_init(&x,0,1);
sem_init(&wsem,0,1);
rc=0;
printf("Enter the no of readers:");
scanf("%d",&nr);
printf("Enter the no of writers");
scanf("%d",&nw);
while(i<nw || j<nr)
{
if(i<nw)
{
pthread_create(&w[i],NULL,writer,(void *)i);
i++;
}
if(j<nr)
{
pthread_create(&r[j],NULL,reader,(void *)j);
j++;
}
}
for(i=0;i<nw;i++)
{
pthread_join(w[i],NULL);
}
for(j=0;j<nr;j++)
{
pthread_join(r[j],NULL);
}
return 0;
}
void *reader(void *arg)
{
FILE *fptr;
sem_wait(&x);
rc++;
if(rc==1)
sem_wait(&wsem);
sem_post(&x);
printf("\nreader %d:",arg);
fptr=fopen("temp.txt","r+");
while(fgets(str,10,fptr)!=NULL)
{
printf("%s",str);
}
printf("\n");
fclose(fptr);
sem_wait(&x);
rc--;
if(rc==0)
sem_post(&wsem);
sem_post(&x);
}
void *writer(void *arg)
{
FILE *fptr1;
sem_wait(&wsem);
printf("\nwriter-%d:\n",arg);
fptr1=fopen("temp.txt","a+");
printf("enter the string:");
scanf("%s",str);
fputs(str,fptr1);
fclose(fptr1);
sem_post(&wsem);
}

Related

C++: Accessing a structure array's element crashes the program

I'm trying to learn structures and I have a program which crashes for me - can't understand why. The compiler throws out a bad access exception when trying to access an element of an array of structures.
Here's the code:
#include <iostream>
#include <fstream>
FILE *input;
int n=1;
struct Student {
string name;
string city;
int grades[4];
};
Student *students = new Student[n];
int main(int argc, const char * argv[]) {
input = fopen("input.txt", "r");
if(input==NULL) {
cout<<"\nCan't open file input.txt";
return;
}
int size;
if(fscanf(input, "Size%d\n\n",&size)<=0) {
cout<<"\nAn error occurred.";
return;
}
n=size;
cout<<"\nThe size is "<<n;
for(int i=0;i<n-1;i++) {
Student newStud;
char name[255];
char city[255];
fscanf(input, "\n%s\n%s\n%d;%d;%d;%d;",name,city,&newStud.grades[0],&newStud.grades[1],&newStud.grades[2],&newStud.grades[3]);
newStud.fullName = name;
newStud.city = city;
cout<<"\nAdding student at "<<i;
students[i]=newStud;
cout<<"\nAdded successfully";
}
fclose(input);
cout<<"\nLoad complete!";
}
input.txt:
Size5
Bob
NY
10;10;10;10;
Rick
SF
6;6;6;6;
John
NY
2;3;2;5;
Jack
NY
5;5;5;4;
Console output:
The size is 5
Adding student at 0
Added successfully
Adding student at 1
The initialization of the students pointer is done before the execution of main. You wouldn't have read n by then. Therefore, your code ends up allocating memory for 1 Student in students array.
The code in your main assumes that the students array is capable of holding size (or the current value of n) while it isn't really the case. Hence, the code ends up accessing unknown locations which causes undefined behavior (a segmentation fault almost always).
The fix is to allocate memory for the array after the input for n has been taken.
Obviously,the program crashed when you tried to access the second Student in the array while you only allocated one size of the Student for it. You should allocate the array’s memory after the code “n = size” but not before,which you did at the top of the main entrance is absolutely unreasonable for your purpose.

push object in the heap using pointer to the static container

class Node_Str{
public:
string name;
string value;
string type;
Node_Str(string name,string value,string type){
name=name;
value=value;
type=type;}};
static stack<Node_Str> s;
void find_token(string input){
int cursor=0;
string current="";
while(cursor<input.length()){
char value;
value=input[cursor];
cout<<value<<endl;
if(value=='('||value==')'||value=='+'||value=='-
'||value=='*'||value=='/'){
Node_Str* p=new Node_Str("pare",string(1,value),"Pare");
s.push(*p);
cursor++;
delete p;}
if(value==' '){
cursor++;
}
if(value=='1'||value=='2'||value=='3'||value=='4'){
Node_Str* p=new Node_Str("num",string(1,value),"Number");
s.push(*p);
cursor++;
delete p;}}}
int main(){
while(!s.empty()){
cout<<s.top().value<<" ";
s.pop(); }
return 0; }
The find_token function should separate the input string by white Space and constructing the Node_Str object with the value of that string. Then in the
main function, I would like to print it. The characters are limit. Just '1', '2','3','4','+,'-','*','/'.
Input is 4 + 4 , output should be 4+4. However, there is no output.
The comments already said about memory leak and forgetting to call find.
In addition to that, stack is a container in which to last to be pushed in would be the first to be popped out. In order to output 0 1 2 3, you would need to push in the stack in the sequence of 3 2 1 0.
Just giving a better version.
#include <iostream>
#include <stack>
using std::cout;
using std::stack;
static stack<int> s;
void find()
{
int* p;
for (int i = 3; i >= 0; i--) {
p = new int(i);
s.push(*p);
delete p; // p itself does not have to be returned so it can be safely deleted here
//This can also ne replaced by directly using s.push(i)
}
}
int main() {
find();
while (!s.empty())
{
cout << s.top() << " ";
s.pop();
}
return 0;
}
as suggested by leyanpan, data should be pushed into reverse order, to get the desired output. One more point is no need of dynamic allocation for int type. It is always better to store non array built in types in stack rather than heap.
Also allocating stack data structure as static variable will extend scope up to program termination. Better to use stack object as a local variable in main and pass it as are reference argument to function find.

Adding element to array of struct c++

Can someone explain why this code does not work? It keeps crashing when it asks for input in addCar().
I think something is wrong with copying an array, but I can't figure out what exactly. I also tried to use copy() but it didn't work either.
#include <iostream>
#include <string>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct Car{
string Brand;
string model;
long mileage;
};
void addCar(int *ptr, struct Car *arra){
*ptr=*ptr+1;
Car *newArr = new Car[*ptr];
memcpy(newArr, arra, (*ptr)*sizeof(Car));
cout<<"Brand ";
getline(cin,newArr[*ptr].Brand);
cout<<"Model ";
getline(cin, newArr[*ptr].model);
cout<<"mileage ";
cin>>newArr[*ptr].mileage;
arra=newArr;
};
int main(int argc, char** argv) {
int size=1;
int *ptr_size;
ptr_size=&size;
Car *tab=new Car[*ptr_size];
tab[0].Brand = "Audi";
tab[0].model = "A8";
tab[0].mileage = 14366;
addCar(*ptr_size, tab);
return 0;
}
The fail is probably here:
getline(cin,newArr[*ptr].Brand);
A bit above, you did this: *ptr=*ptr+1; and made newArr an array of *ptr elements. Arrays are origin zero. That means the first item in the array is newArr[0]. The last will be at newArr[*ptr-1], so writing into newArr[*ptr] is writing over someone else's memory. Generally a bad thing to do.
But this is also not cool:
*ptr=*ptr+1;
Car *newArr = new Car[size+1];
memcpy(newArr, arra, (*ptr)*sizeof(Car));
You increment the size of the array. That's OK.
You create a new array with the new size. That's OK.
You copy new size number of elements from the old array to the new array and over shoot the end of the old array. Not OK.
The best answer is given by Jerry Coffin and Paul McKenzie in the comments: use a std::vector. If this is not allowed... Ick.
But alrighty then.
First, memcpy literally copies a block of memory. It does not know or care what that block of memory is or what it contains. Never use memcpy unless you are copying something really, really simple like basic data type or a structure made up of nothing but basic data types. String is not basic. The data represented by a string might not be inside the string. In that case, you copy a pointer to the string and that pointer will not be valid after the death of the string. That's not a problem in your case because you don't kill the string. That leads to problem 2. Let's fix that before you get there. The easiest way (other than vector) is going to be:
for (int index = 0; index < *ptr-1; index++)
{
newArr[index] = arra[index];
}
An optimization note. You don't want to resize and copy the array every time you add to it. Consider having two integers, one size of array and the other index into array and double the size of the array every time the index is about to catch up with the size.
When you allocate any memory for data with new somebody has to clean up and put that memory back with delete. In C++ that somebody is you. so, before you arra=newArr; you need to delete[] arra;
Passing in the array index as a pointer overcomplicates. Use a reference or just pass by value and return the new index. Also, don't name a variable ptr. Use something descriptive.
void addCar(int &arrasize, struct Car *arra){
or
int addCar(int arrasize, struct Car *arra){
Next problem: int addCar(int arrasize, struct Car *arra){ passes in a pointer to arra. But you passed the pointer by value, made a copy of the pointer, so when you change the pointer inside the function, it's only the copy that got changed and the new array is not going to come back out again. So,
int addCar(int arrasize, struct Car * & arra){
Passes in a reference to the pointer and allows you to modify the pointer inside the function.
Putting all that together:
int addCar(int size, struct Car * & arra)
{
Car *newArr = new Car[size + 1];
for (int index = 0; index < size; index++)
{
newArr[index] = arra[index];
}
cout << "Brand ";
getline(cin, newArr[size].Brand);
cout << "Model ";
getline(cin, newArr[size].model);
cout << "mileage ";
cin >> newArr[size].mileage;
delete[] arra;
arra = newArr;
return size+1;
}
int main()
{
int size=1;
Car *tab=new Car[size];
tab[0].Brand = "Audi";
tab[0].model = "A8";
tab[0].mileage = 14366;
size = addCar(size, tab);
// do more stuff;
// bit of test code here
for (int index = 0; index < size; index++)
{
cout << "Car " << index << " brand =" <<tab[index].Brand << " Model=" << tab[index].model << " mileage=" <<tab[index].mileage << endl;
}
delete[] tab;
return 0;
}
When you are copying the old array to the new one you are accessing invalid memory, remember that, in that point, arra has size *ptr-1 not *ptr, so the line should be
memcpy(newArr, arra, (*ptr-1)*sizeof(Car));
also in the other lines you should insert the new value in the *ptr-1 position because the indexes in newArr go from 0 to size-1 ie *ptr-1:
cout<<"Brand ";
getline(cin,newArr[*ptr-1].Brand);
cout<<"Model ";
getline(cin, newArr[*ptr-1].model);
cout<<"mileage ";
cin>>newArr[*ptr-1].mileage;

Segfault with std::list usage

I'm Java user coming over to C++, and I am having a hard time understanding what is going wrong with this statement. My program has been segfaulting anywhere I put the push_back command. So I'm wondering what exactly is going on.
class Process {
public:
int nice;
int arrivalTime;
int cpuBursts;
list<int> burstList;
Process() {
burstList.push_back(10); // Segfaults here...
}
};
Here is the full code:
#include<iostream>
#include<stdlib.h>
#include<fstream>
#include<list>
#include<string.h>
using namespace std;
int calcTimeslice(int priority);
int calcOriginalPrio(int nice);
int readFile(int ,char **);
int calcPrioBonus(int,int);
void tokenizeAndAdd(char *);
class Bursts {
public:
int isCPUBurst;
int time;
Bursts() {}
// Constructor to make it easier to add to list
Bursts(int tempIsCPU, int tempTime) {
isCPUBurst = tempIsCPU;
time = tempTime;
}
};
class Process {
public:
int nice;
int arrivalTime;
int cpuBursts;
list<int> burstList;
Process() {
burstList.push_back(10);
}
};
int main(int arg, char **argv) {
// This is if the file was not correctly read into the program
// or it doesnt exist ...
if(readFile(arg,argv)==-1) {
cout << "File could not be read. \n";
return -1;
}
//cout << "Original Calc Whatever: " << calcOriginal(19) << '\n';
return 0;
}
/*
* Calculates the timeslice based on the priority
*/
int calcTimeslice(int priority) {
double finalCalc;
// This is the given function in the prompt
finalCalc = ( (1 - (priority / 140)) * 290 + (.5) ) + 10;
// Cast to int, this will be a truncate
return ((int)finalCalc);
}
int readFile(int arg, char **argv) {
char *temp,*pointer;
int endOfFile = 1;
// While its not the end of the file
while(endOfFile) {
// Read in the input from stdin
fgets(temp,256,stdin);
// Check to see if this line had a * in it
if(*temp =='*')
endOfFile = 0;
else
tokenizeAndAdd(temp);
}
return 0;
}
void tokenizeAndAdd(char *string) {
char *token = strtok(string," \n");
int i = 0;
Process p;
while(token != NULL) {
cout << token << endl;
if(i>2) { // If it is odd (CPU burst)
if(i%2 == 1) {
int tempInt = atoi(token);
//p.burstList.push_back(tempInt);
}
else { // If it is even (IO burst)
int tempInt = atoi(token);
//p.burstLis.push_back(tempInt);
}
}
else if(i==0)
p.nice = atoi(token);
else if(i==1)
p.arrivalTime = atoi(token);
else if(i==2)
p.cpuBursts = atoi(token);
token = strtok(NULL," \n");
i++;
}
//cout << p.nice << " " << p.arrivalTime << " " << p.cpuBursts << "\n";
//i = 0;
//cout << p.burstList.size() << "\n";
// cout <<
//}
return;
}
/*
* Calculates and returns the original priority based on the nice number
* provided in the file.
*/
int calcOriginalPrio(int nice) {
double finalCalc;
// This is the given function from the prompt
finalCalc = (( nice + 20 ) / 39 ) * 30 + 105.5;
// Cast to int, this is a truncate in C++
return ((int)finalCalc);
}
/*
* Calculates the bonus time given to a process
*/
int calcPrioBonus(int totalCPU, int totalIO) {
double finalCalc;
// How to calculate bonus off of the prompt
if(totalCPU < totalIO)
finalCalc = ( (1 - (totalCPU / (double)totalIO)) * (-5)) - .5;
else
finalCalc = ( (1 - (totalIO / (double)totalCPU)) * 5) + .5;
// Cast to int
return ((int)finalCalc);
}
You are using temp uninitialized in the following code:
char *temp;
...
while(endOfFile) {
fgets(temp,256,stdin);
...
This can have any side effect, since it most likely destroys your stack or parts of the heap memory. It could fail immediately (when calling the fgets() function), it could fail later (as in your sample) or it could even run fine - maybe until you upgrade your OS, your compiler or anything else, or until you want to run the same executable on another machine. This is called undefined behaviour.
You need to allocate space for the temp variable, not a pointer only. Use something like
char temp[256];
...
while(endOfFile) {
fgets(temp,256,stdin);
...
For more information, see the fgets() documentation. The first parameter is a pointer to a char array - that is where fgets() will store the bytes which have been read. In your code, you pass an uninitialized pointer which means that fgets() will store the bytes to an undefined memory location - this is catched by the OS which terminates your application with a segmentation fault.
BTW: You should consider enabling pedantic warnings when compiling - I compiled with
g++ -Wall -pedantic -o list list.cpp
which gave me the following warning:
list.cpp: In function 'int readFile(int, char**)':
list.cpp:76:26: warning: 'temp' may be used uninitialized in this function [-Wuninitialized]
This is probably not the actual code with the error you report. But here is one of the problems with give you UB.
char *temp,*pointer; // uninicialized pointer char temp[1000]; could work?
int endOfFile = 1;
// While its not the end of the file
while(endOfFile) {
// Read in the input from stdin
fgets(temp,256,stdin);
The last function call will read a maximum of 256 bytes from stdin and will write it in the memory pointed by pointer tmp. So, you need to first "prepare" that memory. But with char *tmp; you only define a pointer, with no defined value, that is, with point to some possible unexisting or illegal/inaccessible for you memory. In contrary, char tmp[1000]; will define in the "stack memory" a block of 1000 bytes, with you can point to using simple the variable tmp. Hope this is clear for you.
EDIT:
I don't know why that would change the behavior of the list,
You are right. That is Undefined Behavior (UB). When you write in some unknown memory (pointed by an uninitialized pointer) you may overwrite data or even code that will broke somewhere the correct function of your program in an unpredicted way.
You will need to learn more about pointers but better you use std::string, and look how parse your file using string and stringstream. That will manage for you the memmory,

C++ Multidimensional arrays generating segmentation faults?

I am writing a script which must copy some names into a multidimensional array, print the contents of the array and then deallocate the memory and terminate. The problem I am having is that when I run the script it only prints out the last name entered. Here is what I have done. Any help would be great! Thanks in advance!
#include <iostream>
#include <string.h>
using namespace std;
void createArray(int n);
void addDetail(char*& name, char*& surname);
void printArray();
void clear();
char ***details;
int used;
int size;
int main()
{
createArray(3);
char* tmpName = new char[20];
char* tmpSurName = new char[120];
strcpy(tmpName, "nameA");
strcpy(tmpSurName, "surnameA");
addDetail(tmpName,tmpSurName);
strcpy(tmpName, "nameB");
strcpy(tmpSurName, "surnameB");
addDetail(tmpName,tmpSurName);
strcpy(tmpName, "nameC");
strcpy(tmpSurName, "surnameC");
addDetail(tmpName,tmpSurName);
clear();
return 0;
}
void createArray(int n)
{
details= new char**[n];
for(int i=0; i<n; i++)
details[i] = new char*[2];
size = n;
used = 0;
}
void addDetail(char*& name, char*& surname)
{
if(occupation < size)
{
details[used][0] = name;
details[used][1] = surname;
used++;
}else{
cout << "Array Full " << endl;
}
}
void printArray()
{
for(int i=0; i<used; i++)
cout << details[i][0] << " " << details[i][1] << endl;
}
void clear()
{
for(int i=0; i<size; i++)
{
delete [] details[i];
details[i] = 0;
}
delete [] details;
details=0;
}
You didn't allocate memory for details[used][0] and details[used][1] so it's using whatever random address was in those locations.
Since this is C++ you can use string instead perhaps? std::string **details;. This should work with your existing code, except that it will leak memory.
Better still is to use a vector of vectors.
Something like:
std::vector<std::vector<std::string> > details;
Then the createArray function can go away completely and addDetail becomes simpler:
std::vector<string> newName;
newName.push_back(name);
newName.push_back(surname);
details.push_back(newName);
It is because each time, you are effectively storing the pointer tmpName and tmpSurName in the array details. Then in the next iteration, you overwrite the contents of the memory where tmpName and tmpSurName point to, so at the end you'll have a list that contains the last name/surname n times.
To solve it, you need to re-allocate tmpName and tmpSurName before each call to addDetail.
Btw, why do you need to use an (ewww) char***, and can't use e.g. the STL?
What it looks like is happening is that you are not adding the string to the array, you are adding a pointer to name and surname. Every instance is pointing at that variable, so when you ask the array what it contains it goes and asks name and surname, which will only contain the last value.
Also that array, are you sure its working how you want it to work? Arrays are... concrete things. Your essentially saying "I want 5 of these, they will be this big (based on the type you put in)" and the computer quietly goes "well I'll set aside space for those here and you can put them in when your ready". When your code puts those names in there, there really isn't any prep on where to store them. If you fill up that space and go beyond you go to bad places. So what you should do is have that last * of char*** be a pointer to a char[120] so that you know (for your purposes atleast) it never gets filled up. Do that in your createArray function after you have created the outer arrays.
You keep overwriting your temporary buffers rather than making new buffers for each entry in the array. As a result, only the last data written to the buffer survives.
Here's a rough guide on one way to fix it, though this sample may have some problems - I made no attempt to compile or test this.
This portion of main belongs in addDetail:
char* tmpName = new char[20];
char* tmpSurName = new char[120];
strcpy(tmpName, "nameA");
strcpy(tmpSurName, "surnameA");
So, your new addDetail would look something like:
void addDetail(char*& name, char*& surname)
{
if(occupation < size)
{
details[used][0] = new char[20];
details[used][1] = new char[120];
strcpy(details[used][0], name);
strcpy(details[used][1], surname);
used++;
}else{
cout << "Array Full " << endl;
}
}
And it would be called from main like:
addDetail("nameA", "surnameA");
You'd need to update clear to properly cleanup the allocations made in addDetail though.