0

i have a custom class, let's call it "Student" and a main method. I'm instanciating the class, and just want to output the content of the class.

My programm crashes with a: Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

Actual Code

Student.h

#ifndef PROG2_STUDENT_H
#define PROG2_STUDENT_H

#include <iostream>

class Student
{
private:
    char *name;

    char *firstName;

    unsigned matriculationNumber;

    unsigned semester;

public:
    Student(char *name, char *firstName, unsigned matriculationNumber, unsigned semester);

    ~Student();

    friend std::ostream &operator<<(std::ostream &ostream, const Student &student);
private:
};

#endif

Student.cpp

#include <cstring>
#include "Student.h"

Student::Student(char *name, char *firstName, unsigned matriculationNumber, unsigned semester)
{
    std::strcpy(this->name, name);
    std::strcpy(this->firstName, firstName);

    this->matriculationNumber = matriculationNumber;
    this->semester            = semester;
}

Student::~Student()
{
    delete[] this->name;
    delete[] this->firstName;
}

std::ostream &operator<<(std::ostream &stream, const Student &input)
{
    stream << input.name << ", " << input.firstName << ": "
           << input.semester << " Semester, MA " << input.matriculationNumber;

    return stream;
}

and my main

#include <iostream>
#include "StudentPackage/Collection/StudentCollection.h"

int main()
{
    Student studentOne((char *)"Testerson", (char *)"Test", 12345, 2);
    std::cout << studentOne << std::endl;

    return 0;
}

What i have tried

I have tried several things, including memcpy. But with memcpy I'm not able to detect the size of the char array correctly.

When i change the Student Constructor to the following, i get problems with the delete/free in the destructor. I guess, this isn't the correct way anyway, but this is happening, because the scope of the input variables are destroyed before the class destructor is called, correct?

Student::Student(char *name, char *firstName, unsigned matriculationNumber, unsigned semester)
{
    this->name      = name;
    this->firstName = firstName;

    this->matriculationNumber = matriculationNumber;
    this->semester            = semester;
}

Question

  1. How can i correctly copy the char array from constructor (name to this->name)?
  2. How can i correctly copy the char array from constructor (firstName to this->firstName)?
Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
Ulf Tietze
  • 57
  • 6
  • 2
    You forgot to allocate any memory. – molbdnilo May 22 '21 at 06:40
  • The parameters should be `const char*`, not `char*`. (I suspect that you got a compilation error, but fixed it in the wrong place.) – molbdnilo May 22 '21 at 06:41
  • 1) Even if `std::strcpy` allocated memory, you should never use `delete[]` on anything that was not obtained with `new T[n]`. 2) Use `std::string`. – Evg May 22 '21 at 06:51
  • But why the (const char*)? What if i want to implement a method like: `changeName(char* newName)`? Would this be fine to declare `const char* newName` as well? – Ulf Tietze May 22 '21 at 07:05
  • @Evg i would love to use std::string, but this is a instruction of my professor ^^ I have to build around this. But what to you mean with `new T[n]`? Why do i need a `new` operator in here? – Ulf Tietze May 22 '21 at 07:06
  • If you want to manage memory manually, you have several possibilities, but allocation and deallocation functions should always match each other. If you allocate with `new`, you use `delete`, if you allocate with `new[]`, you use `delete[]`, if you allocate with `malloc()`, you use `free()`. `std::strcpy()` doesn't allocate memory: it is your responsibility to provide a buffer that is large enough, i.e. you should first initialize `this->name` with something meaningful. Don't forget about the space for the terminating null character. – Evg May 22 '21 at 07:16
  • *Would this be fine to declare `const char* newName` as well?* - Yes if `changeName(x)` is not supposed to modify the buffer pointed at by `x`, and I guess it's not. – Evg May 22 '21 at 07:22

1 Answers1

0

std::strcpy does not allocate memory. So your program is copying input to a "garbage" address that is occurred in the memory area where your Student object is placed. And as result no surprise that you are getting segment violation as result. There are two solutions:

  • a "C-style" way - allocate memory manually (i.e. like auto n = std::strlen(name); this->name = new char[n + 1]; std::strcpy(this->name, name);), but then you need to delete it manually (i.e. delete name;) in the destructor. btw, n + 1 because you also need room for the null-terminator, strlen result does not include it.
  • much better and more "C++" way - use std::string (i.e. declate name member variable as std::string). Then you just can do an asignment: this->name = name;, and no need manual memory management - std::string will take care.
  • (Code style) Also recommend to use some prefix or postfix for member variables, i.e. like m_name(more "Microsoft" style), or name_ - more "Google" style, to avoid those unnecessary this->.
ivan.ukr
  • 2,853
  • 1
  • 23
  • 41