0

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

主.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];
    }
}

当我运行程序时,我得到以下信息:

在此处输入图像描述

在此处输入图像描述

现在这也是一件有趣的事情:如果我将以下几行的顺序转换为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 ++的新手,所以如果有人能看到问题所在,我将不胜感激:)谢谢您的帮助!

4

2 回答 2

2

这里可能的问题之一是您正在使用strcpy

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

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

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

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

于 2013-11-07T12:44:10.683 回答
2

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

如果要将随机字母数组转换为 C 样式字符串,则需要在末尾再添加一个元素,并将其设置为值 0。或者,您需要将strcpy()调用转换为memcpy()调用并提供长度直接地。

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

    char set[list.size()];

对此:

    char set[list.size() + 1];
    set[list.size()] = 0;

然后将所有new char[size_]呼叫更改为new char[size_ + 1].

更简洁的方法是说出您的意思,并将其视为 数组char,而不是 C 字符串。将您的所有strcpy呼叫转换为memcpy. 例如,这个:

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

变成这样:

    memcpy(set_,s,size_);
    memcpy(original_,s,size_);

注意:请务必在这些阵列上全部 strcpy更改为。memcpy我认为至少还有一个。我没有仔细检查你的代码。

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

此外,上面的代码会泄漏内存。如果它只运行一次并退出,这可能不是问题。你new []的记忆,你从来没有delete []。如果您的程序将要增长并且这些对象的多个实例来来往往,您将需要添加这些delete[]调用,否则您将自己设置为将来发生不同类型的崩溃。

于 2013-11-07T12:44:36.190 回答