【问题标题】:Seg Fault when initializing array初始化数组时出现段错误
【发布时间】:2011-04-18 10:21:31
【问题描述】:

我正在学习 C 语言课程,但遇到了分段错误。据我了解,当您访问尚未分配的内存或超出范围的内存时,应该会发生段错误。 '当然,我要做的只是初始化一个数组(虽然相当大)

我只是误解了如何解析二维数组吗?错误放置边界正是导致 seg 错误的原因——我为此使用嵌套的 for-loop 是否错了?

教授提供了时钟功能,所以我希望这不是问题。我在 Cygwin 中运行这段代码,这可能是问题吗?源代码如下。也使用 c99 标准。

非常清楚:我正在寻求帮助来理解(并最终修复)我的代码产生段错误的原因。

#include <stdio.h>
#include <time.h>
int main(void){
   //first define the array and two doubles to count elapsed seconds.   
   double rowMajor, colMajor;
   rowMajor = colMajor = 0;
   int majorArray [1000][1000] = {};

   clock_t start, end;

   //set it up to perform the test 100 times.
   for(int k = 0; k<10; k++)
   {
   start=clock();
   //first we do row major
   for(int i = 0; i < 1000; i++)
   {
       for(int j = 0; j<1000; j++)
       {
           majorArray[i][j] = 314;
       }
   }
   end=clock();
   rowMajor+= (end-start)/(double)CLOCKS_PER_SEC;
   //at this point, we've only done rowMajor, so elapsed = rowMajor
   start=clock();
   //now we do column major
     for(int i = 0; i < 1000; i++)
   {
       for(int j = 0; j<1000; j++)
       {
           majorArray[j][i] = 314;
       }
   }
   end=clock();
   colMajor += (end-start)/(double)CLOCKS_PER_SEC;
   }
   //now that we've done the calculations 100 times, we can compare the values.
   printf("Row major took %f seconds\n", rowMajor);
   printf("Column major took %f seconds\n", colMajor);
   if(rowMajor<colMajor)
   {
     printf("Row major is faster\n");
   }
   else
   {
      printf("Column major is faster\n");
   }

   return 0;

}

【问题讨论】:

  • 这是一个很好的家庭作业问题。写得很好,经过深思熟虑,一些人的回答实际上教会了我一些我不知道的东西(特别是堆栈大小限制)。我赞扬你,OP。
  • 与您的问题无关,但鉴于这是家庭作业:您的第一个 start=time(); 似乎在错误的位置,它应该在 for 循环之前,否则它会重置每个循环,毫无目的

标签: c for-loop segmentation-fault multidimensional-array


【解决方案1】:

您的程序在我的计算机 (x86-64/Linux) 上正常运行,因此我怀疑您遇到了系统特定的调用堆栈大小限制。我不知道您在 Cygwin 上获得了多少堆栈,但您的数组是 4,000,000 字节(使用 32 位 int) - 这很容易太大。

尝试将majorArray 的声明移出main(将其放在#includes 之后)——然后它将成为一个全局变量,它来自一个可能更大的不同分配池。

顺便说一下,这个比较是倒过来的:

if(rowMajor>colMajor)
{
  printf("Row major is faster\n");
}
else
{
   printf("Column major is faster\n");
}

此外,要进行这样的测试,您确实应该针对许多不同的数组大小和形状重复该过程。

【讨论】:

  • 哦,哎呀。谢谢你的收获! ^.^;;另外:将majorArray 移出main 函数就行了,谢谢!
【解决方案2】:

您正试图在堆栈上获取1000 * 1000 * sizeof( int ) 字节。这比您的操作系统允许堆栈增长更多。如果在任何 Unix 上 - 检查 ulimit -a 以获得进程的最大堆栈大小。

根据经验 - 使用malloc(3) 在堆上分配大结构。或者使用静态数组 - 超出任何函数的范围。

在这种情况下,您可以将majorArray 的声明替换为:

int (*majorArray)[1000] = calloc(1000, sizeof majorArray);

【讨论】:

    【解决方案3】:

    我在您的代码中找不到任何错误,因此我编译并运行它并按预期工作。

    但是,您的代码中存在语义错误:

       start=clock();
       //set it up to perform the test 100 times.
       for(int k = 0; k<10; k++)
       {
    

    应该是:

       //set it up to perform the test 100 times.
       for(int k = 0; k<10; k++)
       {
       start=clock();
    

    另外,最后的条件应该改为它的逆:

    if(rowMajor<colMajor)
    

    最后,为了避免其他人提到的特定于操作系统的堆栈大小问题,您应该在 main() 之外定义您的矩阵:

    #include <stdio.h>
    #include <time.h>
    
    int majorArray [1000][1000];
    
    int main(void){
       //first define the array and two doubles to count elapsed seconds.   
       double rowMajor, colMajor;
       rowMajor = colMajor = 0;
    

    【讨论】:

    • 谢谢。我自己发现了开始时钟的问题,现在已经更新了 OP 以反映这一点。
    【解决方案4】:

    这段代码在 Linux 下对我来说运行良好,我看不出有什么明显的错误。您可以尝试通过 gdb 对其进行调试。像这样编译它:

    gcc -g -o testcode test.c
    

    然后说

    gdb ./testcode
    

    在 gdb 中说run

    如果它崩溃了,说where,gdb 会告诉你崩溃发生在哪里。那么你现在错误在哪一行。

    【讨论】:

      【解决方案5】:

      该程序通过 gcc 编译并在 Linux 中运行时运行良好,Cygwin 很可能是您的问题。

      【讨论】:

        【解决方案6】:

        如果它在其他地方正常运行,您很可能试图获取比操作系统允许的更多的堆栈空间。您在堆栈上分配 4MB(1 个整数),这对于在堆栈上“安全”分配来说太多了。 malloc() 和 free() 是你最好的选择。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-07-30
          • 2013-10-04
          • 2021-05-18
          • 1970-01-01
          • 1970-01-01
          • 2011-12-20
          • 2017-07-24
          • 1970-01-01
          相关资源
          最近更新 更多