C ++为什么这个传递引用的数组会产生运行时错误?

时间:2009-01-22 16:45:12

标签: c++ pass-by-reference

void pushSynonyms (string synline,  char  matrizSinonimos [1024][1024]){


             stringstream synstream(synline);

             vector<int> synsAux;


             int num;

             while (synstream >> num) {synsAux.push_back(num);}


             int index=0;
             while (index<(synsAux.size()-1)){

                   int primerSinonimo=synsAux[index];
                   int segundoSinonimo=synsAux[++index];
                   matrizSinonimos[primerSinonimo][segundoSinonimo]='S';
                   matrizSinonimos [segundoSinonimo][primerSinonimo]='S';

                   }

           } 

和电话..

char matrizSinonimos[1024][1024];
     pushSynonyms("1 7", matrizSinonimos)

通过引用传递matrizSinonimos非常重要。

编辑:带走了&amp;来自&matrizSinonimos

编辑:运行时错误是:

An unhandled win32 exception occurred in program.exe [2488]![alt text][1]

6 个答案:

答案 0 :(得分:5)

它出了什么问题

你在那里的代码 - 我找不到一个bug。我发现的唯一问题是,如果你根本没有提供任何数字,那么这部分将造成伤害:

(synsAux.size()-1)

它会从0u中减去1。这将包围,因为size()返回无符号整数类型。你将得到一个非常大的值,大约2 ^ 16或2 ^ 32。您应该将整个条件更改为

while ((index+1) < synsAux.size())

您可以尝试在呼叫方面查找错误。通常会发生在此之前的某处发生缓冲区溢出或堆损坏,并且程序因此而在程序中的稍后点崩溃。

其中的参数和参数内容

关于阵列及其如何通过,我认为你做得很好。虽然,您仍然按值传递数组。也许你已经知道了,但我会重复一遍。你真的传递了一个指向这个数组的第一个元素的指针:

char matrizSinonimos[1024][1024];

2d数组确实是一个数组数组。该数组的第一个元素是一个数组,指向它的指针是一个指向数组的指针。在那种情况下,它是

char (*)[1024]

即使在参数列表中你说你接受了一个数组数组,编译器会一如既往地调整它并使它成为指向这种数组的第一个元素的指针。所以实际上,在编译器调整参数类型之后,你的函数有了原型:

void pushSynonyms (string synline,  char (*matrizSinonimos)[1024]);

尽管经常建议,您无法将该数组作为char** 传递,因为被调用的函数需要内部维度的大小,以正确地处理正确偏移处的子维度。在被调用函数中使用char**,然后编写类似matrizSinonimos[0][1]的内容,它将尝试将该数组的第一个sizeof(char **)字符解释为指针,并尝试取消引用一个随机的内存位置,然后第二次这样做,如果它之间没有崩溃。 不要那样做。它与您在该数组的外部维度中编写的大小无关。它合理化了。现在,通过引用传递数组并不重要。但如果你愿意,你必须将整个事情改为

void pushSynonyms (string synline,  char (&matrizSinonimos)[1024][1024]);

通过引用传递不会传递指向第一个元素的指针:保留所有维度的所有大小,并传递数组对象本身而不是值。

答案 1 :(得分:4)

数组作为指针传递 - 不需要对它们进行传递引用。如果您将函数声明为:

void pushSynonyms(string synline, char matrizSinonimos[][1024]);

您对阵列的更改将持续存在 - 数组从不按值传递。

答案 2 :(得分:3)

异常可能是0xC00000FD,或堆栈溢出!

问题是你在堆栈上创建一个1 MB的数组,这可能太大了。

答案 3 :(得分:0)

编辑1 )我忘记回答您的实际问题了。好吧:在你纠正了代码以正确的方式传递数组(没有不正确的间接)之后,我似乎很可能你没有正确检查输入。您从流中读取,将其保存到矢量中,但您从未检查到达的所有数字是否实际上都在正确的范围内。 (结束编辑1

第一的: 使用原始数组可能不是您真正想要的。有std::vectorboost::array。后者是像原始数组一样的编译时固定大小数组,但提供了C ++集合类型defs和方法,这对于通用(读取:模板化)代码是实用的。

并且,使用这些类可能会减少关于类型安全性,按引用传递,按值传递或传递指针的混淆。

第二: 数组作为指针传递,指针本身按值传递。

第三: 您应该在堆上分配这样的大对象。堆分配的开销在这种情况下是微不足道的,它将减少堆栈空间耗尽的可能性。

void someFunction(int array[10][10]);

确实是:

编辑2 )感谢评论:

void someFunction(int ** array);

void someFunction(int (*array)[10]);

希望我没有在其他地方搞砸.... (结束编辑2

作为10x10阵列的类型信息丢失。为了得到你可能想要的东西,你需要写:

void someFunction(int (&array)[10][10]);

这样编译器可以检查调用者端的数组实际上是10x10数组。然后,您可以像这样调用函数:

int main() {
  int array[10][10] = { 0 };
  someFunction(array);
  return 0;
}

答案 4 :(得分:0)

尝试将其声明为:

void pushSynonyms (const string & synline,  char  *matrizSinonimos[1024] )

我相信会做你想做的事。正如其他人所说,你拥有它的方式会在堆栈上创建一个1MB的数组。此外,将同步从string更改为const string &会消除将完整的字符串副本推送到堆栈上。

另外,我会使用某种类来封装matrizSinonimos。类似的东西:

class ms
{
    char m_martix[1024][1024];
    public:
    pushSynonyms( const string & synline );
}

那么你根本不需要传递它。

答案 5 :(得分:0)

我对上面的代码出了什么问题感到茫然,但是如果你不能让数组语法起作用,你可以随时这样做:

void pushSynonyms (string synline,  char  *matrizSinonimos, int rowsize, int colsize )
{
   // the code below is equivalent to 
   // char c = matrizSinonimos[a][b];
   char c = matrizSinonimos( a*rowsize + b );
   // you could also Assert( a < rowsize && b < colsize );
}

pushSynonyms( "1 7", matrizSinonimos, 1024, 1024 );

如果在编译时已知,则可以使用#define SYNONYM_ARRAY_DIMENSION 1024替换rowsize和colsize,这将使乘法步骤更快。