在c ++中使用cin时内存损坏

时间:2016-03-01 14:23:24

标签: c++ header-files clion

我上课了#34; 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 = "";
};

头文件&#34; student.h&#34;:

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();
};

&#34; main.cpp&#34;:

#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;
}

我正在运行这个美国Clion和Cmake:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")

set(SOURCE_FILES main.cpp student.cpp student.h student.cpp student.h)

但是当我运行时,它会询问名称,但是当我输入内容时,我会遇到内存碎片错误。怎么了? 那么有人可以告诉我它是否适合C ++?我正在尝试从java切换到c ++。

2 个答案:

答案 0 :(得分:6)

char* n;
...
cin>> n;

n是一个指针,应该指向特定的内存。但你永远不会设置它。因此它有一些未定义的值,指向谁知道哪里到你最终试图覆盖的某些内存中。很可能是你不允许覆盖的内存,导致段错误。

如果您还不了解手动内存管理,请不要尝试使用char*(一旦您这样做,您就会明白为什么不这样做)。使用std::string

从快速浏览一下,您几乎可以用char*替换std::string(只要您#include <string>)。

答案 1 :(得分:1)

与其他人的说法相似,您的变量n是未初始化的指针。顾名思义,指针只是指向内存中特定位置的路标 - 告诉CPU&#34;转到此内存位置以获取变量x&#34;。

假设你有一个整数变量var,它的声明如下:

int var;

该变量占用内存,您可以为其分配如下值:

var = 5;

你也可以声明一个指向这样的整数的指针:

int * var_ptr;

现在假设var_ptr指向有效整数,我可以像这样为它分配一个值:

*var_ptr = 5;

这表示&#34;将数字5放在var&#34;指向的内存位置。但是,如果var_ptr尚未初始化,则它将指向内存中可能覆盖重要内容的随机位置,或尝试写入受保护的内存地址,从而导致保护错误(segfault)。这就是你的代码中发生的事情。

要初始化var_ptr以指向var的地址,我们可以这样做:

var_ptr = &var;

&符号是&#34;&#34;地址&#34;运营商 - 它说&#34;没有给我var的价值,而是获取存储var的内存位置的地址&#34;。

因此,为了防止出现问题,您必须将n初始化为某个有效的内存位置,以便您可以安全地写入某些数据。

有几种方法可以做到这一点。正如@Stefan指出的那样,你可以声明n是一个字符数组:

char n[20];

正如@BobTFish所指出的,你需要一些方法来确保你的输入不超过数组的大小(在这种情况下为20字节)。解决方案是std::cin.width(20)

正如@BobTFish也提到的那样,你也可以使用std::string,如下所示:

std::string n;
std:cin >> n;

std::string对象将自动处理内存分配。

如果你真的必须使用char *,你可以取一个char数组的地址(这里我取数组第一个元素的地址):

char n_array[20];
char *n = &n_array[0];
std::cin.width(20);
std::cin >> n;

您还可以使用动态内存分配:

char *n = new char[20];
std::cin.width(20);
std::cin >> n;
delete n;

请注意,如果使用动态内存分配,则必须在完成后使用delete释放内存,否则会出现内存泄漏。局部变量(如数组)在堆栈上分配,因此在函数返回时自动释放。出于这个原因,以及动态内存分配的开销,你在这里使用它会很疯狂。