C++ strcat创建无限循环

问题描述:

我试图创建一个数组,每个对象在数组中应该有名称模型(i)其中是索引,我这样做,使他们将按降序排列的名称Model5,Model4。 ..我试图做到这一点使用char [],但由于某种原因在我的代码中使用for循环内的strcat使我卡住在一个无限循环,第二点,如果有人可以帮助转换索引的方式我可以连接名称并赋予构造函数。C++ 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

如果您使用C++,你应该使用'的std :: string'和相关方法而不是C的'的strcat '与字符数组 –

+4

'm odelo'只能创建到足以容纳您初始化的单词。如果使用'std :: strcat'使内容更长,则您正在写入数组边界之外导致未定义的行为。 – Galik

+0

可能重复的[我只是无法找出strcat](http://*.com/questions/4707900/i-just-cant-figure-out-strcat) –

环路工作正常。我只是不明白为什么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 | 
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
+0

非常感谢你解释@paddy,我决定使用std :: string,所以现在问题已经解决了!但是非常感谢,现在我将在使用char []时知道。 –