我正在为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];
}
}
当我运行程序时,我得到以下内容:
现在这里也是一件有趣的事情:如果我在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 ++的新手,所以如果有人能看到问题,我会很感激:)感谢您的帮助!
答案 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 []
调用,否则你就会为将来的崩溃做好准备。