c++ strcat创建无限循环

C++ strcat creating infinite loop

本文关键字:无限循环 创建 strcat c++      更新时间:2023-10-16

我试图创建一个数组,数组中的每个对象都应该有名称Model(i),其中是索引,我这样做,所以他们将有名称按降序索引Model5, Model4…我试图这样做,使用char[],但由于某种原因,在我的代码中使用strcat内for循环使我陷入无限循环,第二点,如果有人可以帮助转换索引的方式,我可以与名称连接,并给构造函数。

#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
class CARRO {
    public:
        CARRO() {};
        CARRO(char *modelo, unsigned ano);
        char* getModelo();
        unsigned getAno();
    private:
        char modelo[100];
        unsigned ano;
};
void swap(int *p, int *q);
int partition(int *v, int start, int end);
int randomizedPartition(int *v, int start, int end);
void qsHelper(int *v, int start, int end);
void quickSort(int *v, int len);
void printList(CARRO *carros, unsigned len);
int main(int argc, char const *argv[]) {
    CARRO carros[5];
    unsigned len = sizeof(carros)/sizeof(CARRO);
    for (int i = 0; i < len; ++i) {
        char modelo[] = "Modelo";
        char id[] = "I";
        strcat(modelo, id);
        unsigned ano = 1000 * (i+1);
        carros[i] = CARRO(modelo, ano);
        cout << carros[i].getModelo() << endl;
    }
    //printList(carros, len);
    return 0;
}
CARRO::CARRO(char *modelo, unsigned ano) {
    strcpy(this->modelo, modelo);
    this->ano = ano;
}

如果我删除行:

strcat(modelo, id);

循环工作正常。我只是不明白为什么strcat会以某种方式产生无限循环。输出如下:(带strcat行)

ModeloI
ModeloI
ModeloI
ModeloI
ModeloI
ModeloI
ModeloI
ModeloI
ModeloI
ModeloI
^CModeloI

循环工作正常。我只是不明白为什么strcat会以某种方式产生无限循环。输出如下:(带strcat行)

循环不能正常工作!你在破坏记忆。让我们创建一些方框来表示堆栈,因为可能会被您的程序看到(假设循环刚刚转到1):

+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| char modelo[7]                          | int i                 | unsigned len          |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 'M' | 'o' | 'd' | 'e' | 'l' | 'o' | 0   | 1   | 0   | 0   | 0   | 5   | 0   | 0   | 0   |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+

所以当你这样做的时候:

strcat( modelo, id );

最终导致一个字节的缓冲区溢出。在我的特定示例中,这会重写变量i的第一个字节,从而导致循环无限期地继续:

+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| char modelo[7]                          | int i                 |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 'M' | 'o' | 'd' | 'e' | 'l' | 'o' | 'I' | 0   | 0   | 0   | 0   |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
                                           ^^^^^
                                           Nul-terminator written

当然,我这样布置你的堆栈纯粹是作为一个例子。您的编译器可能不会像这样将堆栈保存在一起。有可能是额外的填充后,你的数组和它可能恰好"工作"。变量i 可能保存在寄存器中,而不保存在内存中,或者编译器可能完全展开了循环。您的架构可能是大端序的(而不是像我的例子中那样是小端序的)。

关键是,结果行为是完全未定义的。即使你在你的机器上得到一致的结果,我们也不能看一下这段代码然后说会发生什么。

所以要解决这个问题,你可以简单地使modelo大到足以存储字符串"ModeloI",包括终止符,这意味着使它大到足以存储8字节而不是7:

char modelo[8] = "Modelo";

那么你就定义了行为,不管堆栈是按照下面的方式布局还是以其他方式布局:

+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| char modelo[8]                                | int i                 |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 'M' | 'o' | 'd' | 'e' | 'l' | 'o' | 'I' | 0   | 1   | 0   | 0   | 0   |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+