2013-02-22 27 views
1

我一直被這個問題隨機困擾,我似乎無法弄清楚是什麼導致它。我有一個函數聲明大量的變量,指針和數組。然而,在某個時候,如果我聲明一個新變量,我的程序似乎會崩潰。即使它發生崩潰,它似乎也不一致。如果我的函數下面的代碼,如果我將變量b聲明爲int,它會使程序崩潰,但是如果我聲明它爲int b [10],它將不會。C程序在聲明變量時崩潰

我對很多代碼表示歉意,但我想提供整個功能以防萬一我遺失了一些東西。我所指的變量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); 
} 

任何指導將不勝感激!

編輯*感謝回覆的傢伙!結果發現堆棧的腐敗是正確的答案。我正在努力修復它。

+1

這個症狀總是意味着你的代碼以某種方式覆蓋了堆棧。您需要在調試器(或者更好的是,存儲器違規檢測器,如Valgrind)中運行它,或者通過分析它所做的每個寫操作來確定它失敗的位置。 – unwind 2013-02-22 10:08:08

+0

不是問題的答案,但肯定是很好的指導,請使用Valgrind:http://www.valgrind.org/此處的示例用法:http://www.cs.swarthmore.edu/~newhall/unixhelp/purify.html – nevelis 2013-02-22 10:08:19

回答

1

如果我將變量b聲明爲int,它會使程序崩潰,但是如果我聲明它爲int b [10],它不會。

明顯的原因是,對於後者,您將保留10倍的內存。但是,您似乎並沒有在任何地方使用b,所以幾乎可以肯定,您在其他地方的內存超出了內存。不同之處在於,保留額外的內存可以防止重寫某些關鍵內容的bug(與程序僅在Debug下工作時相同)。

問題是,這只是程序的一部分,實際的錯誤可能是其他地方,因爲您調用其他函數並使用傳入的參數作爲參數。

bottom_field_flag是一個明顯的檢查值。

你沒有提到你得到什麼類型的崩潰。這對進一步解決問題至關重要。例如,如果你得到堆棧溢出,並且你在Windows上,那麼你需要檢查你的編譯器的堆棧大小設置(我認爲/ F和Visual Studio中的一個鏈接器選項)。

0

哪個操作系統?如果這是在Windows那麼這很可能是由您的編譯器插入的chkstk-routine引起的,而不會詢問它何時看到具有> 4k本地人的功能。如果您使用-nostdlib那麼這將失敗。

1

在堆棧上分配過多的大數組是壞主意的想法。堆棧並不意味着這一點,你會很容易用完堆棧內存。更糟的是,很難控制和解決這個問題。

相反,您必須在堆堆上分配大量內存。還有更多的內存有(但不是無限的,當然!)

總之,隨着

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

更換

unsigned char topy[30720]; 

要好得多,可能會消除你的問題。當不再需要時,請不要忘記釋放分配的內存(free(topy))。

UPD:當然,theese是一般的推理,他們適用於特殊情況下(即嵌入式系統等)。

+0

** 50kb **對於非遞歸函數,默認爲1MB的堆棧很好。事實上,如果你不需要它,沒有堆依賴是很好的。 – 2013-02-22 10:18:35

+0

原來我破壞了decode_intra_mb()函數中的堆棧。 我有我的數組聲明,因爲我正在開發這個嵌入式平臺,我不能使用malloc和內存將靜態分配。所以我只是計劃未來我猜 – PumpkinPie 2013-02-22 10:22:36

+0

@eznme我看到了,主要是我的回答是基於一個假設,即OP正在廣泛使用這項技術,並且所有功能*一起*最終都具有臨界質量。不過,我錯了,對不起。當然,如果一個人知道他做了什麼,那麼這樣的堆棧數組沒有任何問題。 – NIA 2013-02-22 12:17:10

0

Valgrind(由@nevelis提議)是解決此類問題的一個非常好的主意。

另一個選擇是使用調試器(gdb)執行應用程序,等待崩潰並查看後面的跟蹤。

在gdb中的命令是:

run 

和崩潰後:

bt 

我想你也應該減少堆棧的大小(自動變量)。 44K堆棧似乎不是一個好主意。