C程序在声明变量时崩溃

时间:2013-02-22 10:05:04

标签: c variables memory crash declaration

我被这个问题随机困扰,我似乎无法弄清楚是什么导致了这个问题。

我有一个声明大量变量,指针和数组的函数。但是在某个时刻,如果我声明一个新变量,我的程序似乎会崩溃。即使它确实崩溃,它似乎也不一致。如果我的函数下面的代码,如果我将变量b声明为int,它将使程序崩溃,但如果我将其声明为int b [10]则不会。

我为大量代码道歉,但我想提供整个功能,以防我遗漏了什么。我所指的变量b靠近顶部。

我怀疑这是某种内存问题,但我所看到的似乎并不真实。

static should_inline void decode_image_internal(PictureDecoderData* pdd, FILE* outfile)
{
  unsigned int mb_row;
  unsigned int mb_col;
  unsigned int mb_idx;
  unsigned int i;
  unsigned int j;
  unsigned int b[10];
  unsigned char topy[30720];
  unsigned char topcb[7680];
  unsigned char topcr[7680];

  Picture* pic = pdd->pic;
  unsigned int bottom_field_flag = pdd->prev_sh->bottom_field_flag; // TODO: remove the     use of prev_sh since it really depends on the pdd decoding context.
  slice_header_t* slice0 = pic->field_sh[bottom_field_flag][0]; // get a slice header.   It is used for variables that are the same for the whole picture
  seq_parameter_set_rbsp_t* sps = slice0->sps;
  pic_parameter_set_rbsp_t* pps = slice0->pps;
  int PicWidthInMbs = sps->PicWidthInMbs;
  unsigned int PicWidthY = PicWidthInMbs * 16;
  unsigned int PicHeightInMbs = slice0->PicHeightInMbs;
  unsigned int PicSizeInMbs = PicWidthInMbs*PicHeightInMbs;
  int CurrMbAddr;
  MbAttrib* mb_attr = pic->field_data[bottom_field_flag].mb_attr;
  MbAttrib* curr_mb_attr;
  unsigned int mbc_width = MbWidthC[1];
  unsigned int mbc_height = MbHeightC[1];
//  unsigned int mbc_size = mbc_width*mbc_height;
  unsigned int PicWidthC = PicWidthInMbs * mbc_width;
  int clipY = (1<<sps->BitDepthY)-1;
  int meanY = 1<<(sps->BitDepthY-1);
  int clipC = (1<<sps->BitDepthC)-1;
  int meanC = 1<<(sps->BitDepthC-1);
  int mb_data_size = (256+2*MbSizeC[1]);
  int16_t* mb_data = pic->field_data[bottom_field_flag].data;
  int16_t* curr_mb_data;
  unsigned int field_pic_flag = slice0->field_pic_flag;
  unsigned int strideY = PicWidthY << field_pic_flag;
  unsigned int strideC = PicWidthC << field_pic_flag;
  slice_header_t* sh;
  unsigned int constrained_intra_pred_flag = pps->constrained_intra_pred_flag;

  pixel_t* Y;
  pixel_t* C[2];
  pixel_t* y;
  pixel_t* c[2];

  Y = (pixel_t*)((uint32_t)pic->Y + (bottom_field_flag!=0)*PicWidthY);
  C[0] = (pixel_t*)((uint32_t)pic->C[0]+ (bottom_field_flag!=0)*PicWidthC);
  C[1] = (pixel_t*)((uint32_t)pic->C[1]+ (bottom_field_flag!=0)*PicWidthC);


  for (j = 0; j<=pic->slice_num[bottom_field_flag]; j++)
  {
    sh = pic->field_sh[bottom_field_flag][j];
    CurrMbAddr = sh->first_mb_in_slice;

    //for (i = 0; i<sh->mb_nb; i++)
     for (i = 0; i<2; i++)
    {
      pixel_t ysamp[256], cbsamp[8*8], crsamp[8*8];
      mb_row = (CurrMbAddr) / PicWidthInMbs;
      mb_col = (CurrMbAddr) % PicWidthInMbs;
      mb_idx = (CurrMbAddr);
      curr_mb_attr = &mb_attr[mb_idx];
      curr_mb_data = mb_data + mb_idx * mb_data_size;
     // printf(" %d %d \n ",strideY, mb_row);
      y = Y + mb_col*16 + mb_row*strideY*16;
      c[0] = C[0] + mb_col*mbc_width + mb_row*strideC*mbc_height;
      c[1] = C[1] + mb_col*mbc_width + mb_row*strideC*mbc_height;


        {
          MB_TYPE mb_type = curr_mb_attr->mb_type;
          unsigned int mb_field_decoding_flag = curr_mb_attr->mb_field_decoding_flag;
          pixel_t* mb_C_samples[2];

          mb_C_samples[0] = c[0];
          mb_C_samples[1] = c[1];


          //if (mb_type <= SI) // Intra mb
            decode_intra_mb(curr_mb_attr, mb_type, curr_mb_data, 1920, 960, y, mb_C_samples[0], mb_C_samples[1],
            ysamp, cbsamp, crsamp,
            mbc_height, mbc_width, clipY, clipC, meanY, meanC, mb_field_decoding_flag, mb_row&1, PicWidthInMbs, 0,
            constrained_intra_pred_flag);

            rgbconvert(ysamp, cbsamp, crsamp, outfile);


        }

      CurrMbAddr = NextMbAddress(sh->MbToSliceGroupMap, CurrMbAddr, PicSizeInMbs, pps->num_slice_groups_minus1);
    }

  }


  // Release the ref picture it was using
  release_picture_refpics(pic, bottom_field_flag); // it is OK even when the pic is a frame because both field points to the same lists

  filter_image(pic, bottom_field_flag);

  // Output the picture !
  add_image_to_dpb(pic);
}

非常感谢任何指导!

编辑*感谢回复家伙们!结果是堆栈的损坏是正确的答案。我正准备修理它。

4 个答案:

答案 0 :(得分:2)

在堆栈上分配太多大型数组是 BAD 的想法。堆栈不适用于此,您将很容易耗尽堆栈内存。更糟糕的是,很难控制并发现这样的问题。

相反,您必须在上分配大量内存。那里有更多的记忆(当然不是无限的!)

简而言之,取代

unsigned char topy[30720];

unsigned char* topy = (char*)malloc(30720);

必须要好得多,可能会消除你的问题。不要忘记在不再需要时释放已分配的内存(free(topy))。

UPD :当然,theese是一般推理,他们适用于特殊情况(即嵌入式系统等)。

答案 1 :(得分:1)

如果我将变量b声明为int会导致程序崩溃,但如果我将其声明为int b [10]则不会。

显而易见的原因是,对于后者,你将保留10倍的内存。但是,您似乎没有在任何地方使用b,因此几乎可以肯定您在其他地方超出了内存。不同之处在于保留额外的内存可以阻止错误覆盖一些关键内容(与程序仅在Debug下工作时相同)。

麻烦的是,这只是程序的一部分,实际错误可能在其他地方,因为你正在调用其他函数并使用作为参数传入的数据。

bottom_field_flag是值得检查的明显值。

你没有提到你得到什么类型的崩溃。这对于进一步采取决议至关重要。例如,如果您遇到堆栈溢出,并且您在Windows上,那么您需要检查编译器中的堆栈大小设置(我认为/ F和Visual Studio中的链接器选项)。

答案 2 :(得分:0)

哪个操作系统?如果这是在 Windows 上,那么这很可能是由编译器插入的chkstk例程引起的,而不会询问它何时看到带有&gt; 4k本地的函数。如果您使用 -nostdlib ,则会失败。

答案 3 :(得分:0)

Valgrind(由@nevelis提出)是解决此类问题的一个非常好的主意。

另一个选择是使用调试器( gdb )执行应用程序,等待崩溃并查看后面的跟踪。

在gdb中,命令是:

run

并在坠机后:

bt

我认为你还应该减少堆栈大小(自动变量)。堆栈上的44K似乎不是一个好主意。