确定C ++程序崩溃的原因

时间:2013-11-07 12:18:42

标签: c++ crash

我正在为PCB装配论文做一个C ++项目,而且(我的教授)给了一套旧的C ++代码。当我尝试测试并运行代码时,它会崩溃......程序编译好了,但它在运行时崩溃了......代码是:

main.cpp中:

#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include <climits>
#include "NozzleBank.h"
#include "PlacementHead.h"

int main (int argc, char * const argv[]) {
    std::vector<char> list;
    for (int i=0; i<3; i++) {list.push_back('a');}
    for (int i=0; i<3; i++) {list.push_back('b');}
    for (int i=0; i<3; i++) {list.push_back('c');}
    for (int i=0; i<3; i++) {list.push_back('d');}
    for (int i=0; i<3; i++) {list.push_back('_');}

    int i = 0;
    char set[list.size()];
    while (!list.empty()) {
        int x = (rand() % list.size());
        set[i] = list.at(x);
        list.erase(list.begin()+x);
        i++;
    }

    NozzleBank bank(15,set);
    PlacementHead head(4,2,1,"abababab");

    return 0;
} 

PlacementHead.cpp:

#include "PlacementHead.h"
#include <string>
#include <iostream>
#include <string.h>

PlacementHead::PlacementHead(int width, int height, int gap, char* s) {
    width_ = width;
    height_ = height;
    gap_ = gap;
    size_ = (width*height)+1;
    set_ = new char[size_];
    from_ = new int[size_];
    original_ = new char[size_];
    strcpy(set_,s);
    strcpy(original_,s);
}

PlacementHead::~PlacementHead() {

}

int PlacementHead::getSize() { return size_; }
int PlacementHead::getHeight() { return height_; }
int PlacementHead::getWidth() { return width_; }
int PlacementHead::getGap() { return gap_; }

// Palauttaa indeksissä i olevan suuttimen
char PlacementHead::getNozzle(int i) {
    return set_[i-1];
}

// Asettaa indeksissä i olevan suuttimen
void PlacementHead::setNozzle(int i, char c) {
    set_[i-1] = c;
}

// Merkitsee suuttimen poimituksi poistamalla sen listasta
void PlacementHead::markNozzle(int i, int bankPos) {
    set_[i-1] = ' ';
    from_[i-1] = bankPos;
}

// Palauttaa seuraavan poimimattoman suuttimen indeksin
int PlacementHead::getNextUnmarkedPos() {
    for (int i=0; i<size_; i++) {
        if (set_[i]!=' ') {
            return i+1;
        }
    }
    return 0;
}

// Palauttaa suuttimen alkuperäisen sijainnin pankissa
int PlacementHead::getBankPos(int i) {
    return from_[i-1];
}

// Plauttaa alkuperäisen ladontapaan suutinjärjestyksen
void PlacementHead::reset() {
    //for (int i=0; i<size_; i++) {
    //  set_[i] = original_[i];
    //}
    strcpy(set_,original_);
}

// Tulostusmetodi
void PlacementHead::print() {
    std::cout << "ladontapää:\n";
    for (int h=height_; h>0; h--) {
        for (int w=width_; w>0; w--) {
            int i = ((h-1)*width_)+w;
            std::cout << getNozzle(i);
        }
        std::cout << "\n";
    }
}

NozzleBank.cpp:

#include "NozzleBank.h"
#include <string>
#include <iostream>
#include <string.h>

NozzleBank::NozzleBank(int size) {
    bank_ = new char[size];
    original_ = new char[size];
    size_=size;
    for (int i=0; i<size_; i++) {
        bank_[i] = ' ';
        original_[i] = ' ';
    }
}

NozzleBank::NozzleBank(int size, char* s) {
    bank_ = new char[size];
    original_ = new char[size];
    size_ = size;
    strcpy(bank_,s);
    strcpy(original_,s);
}

NozzleBank::~NozzleBank() {

}

int NozzleBank::getSize() { return size_; }

// Palauttaa pankin alkuperäisen järjestyksen
void NozzleBank::reset() {
    strcpy(bank_,original_);
}

// Asettaa indeksissä i olevan suuttimen
void NozzleBank::setNozzle(int i, char c) {
    bank_[i-1] = c;
    original_[i-1] = c;
}

// Palauttaa indeksissä i olevan suuttimen
char NozzleBank::getNozzle(int i) {
    return bank_[i-1];
}

// Poimii suuttimen poistamalla sen listasta
void NozzleBank::pickNozzle(int i) {
    bank_[i-1] = ' ';
}

// Tulostusmetodi
void NozzleBank::print() {
    for (int i=size_; i>0; i--) {
        std::cout << bank_[i-1];
    }
}

当我运行程序时,我得到以下内容:

enter image description here

enter image description here

现在这里也是一件有趣的事情:如果我在main.cpp

中切换以下行的顺序
NozzleBank bank(15,set);
PlacementHead head(4,2,1,"abababab");

为:

PlacementHead head(4,2,1,"abababab");
NozzleBank bank(15,set);

程序运行良好......:O?在这里,我变得像whaaaat ......我是C ++的新手,所以如果有人能看到问题,我会很感激:)感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

此处可能存在的问题之一是您正在使用strcpy

strcpy通过读取一个字符数组来工作,直到它到达一个空终止字符'\0' - 但是你的源数组不包含空终止字符。所以strcpy将永远保持复制,读取它无法访问的内存,并写入目标数组的末尾,其中任何一个都可能导致崩溃。你需要使用strncpy(你应该总是喜欢),它只复制固定数量的字符。

如果您打算将字符视为字符串,那么您通常应该在任何字符数组中留出额外的空格,就像strcpy一样。如果您只使用单独的元素并自己处理单个字符,那么您不需要。在这种情况下,你可以同样使用memcpy

代码中可能还有其他问题,这只是我发现的问题。

你也有内存泄漏,你应该删除[]新成员变量[]

答案 1 :(得分:2)

C库strcpy()需要NUL终止的C样式字符串。你有一个没有NUL终结符的char[]数组。

如果要将随机字母数组转换为C风格的字符串,则需要在结尾添加一个元素,并将其设置为值0.或者,您需要转换{{1}调用strcpy()调用并直接提供长度。

就最小代码更改而言,添加NUL终结符需要对代码进行最少的更改。改变这个:

memcpy()

到此:

    char set[list.size()];

然后将所有 char set[list.size() + 1]; set[list.size()] = 0; 次来电更改为new char[size_]

更干净的方法是说出你的意思,并将其视为new char[size_ + 1]的数组,而不是C字符串。将您的所有char来电转换为strcpy。例如,这个:

memcpy

成为这个:

    strcpy(set_,s);
    strcpy(original_,s);

注意:请务必在这些阵列上将所有 memcpy(set_,s,size_); memcpy(original_,s,size_); 更改为strcpy。我认为至少还有一个。我没有密切检查你的代码。

后者是更好的方法,恕我直言,但我同时提供。

此外,上面的代码泄漏了内存。如果它只运行一次并退出,这可能不是一个问题。您永远memcpy的{​​{1}}记忆。如果你的程序会增长并且这些对象的多个实例来来往往,你会想要添加那些new []调用,否则你就会为将来的崩溃做好准备。