C ++ strcat创建无限循环

时间:2016-11-16 00:13:03

标签: c++ loops infinite strcat

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

#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

1 个答案:

答案 0 :(得分:1)

  

循环工作正常。我只是不明白为什么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 可能保存在寄存器中,永远不会保存在内存中,或者编译器可能完全展开循环。你的架构可能是big-endian(而不是像我的例子中的little-endian)。

关键是,结果行为是完全未定义的。即使您在计算机上获得一致的结果,我们也无法查看此代码并说明会发生什么。

因此,为了解决这个问题,您可以简单地使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   |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+